diff --git a/IRC.Core.SCP/Program.cs b/IRC.Core.SCP/Program.cs index 7ac6b53e7..39a3ddfca 100644 --- a/IRC.Core.SCP/Program.cs +++ b/IRC.Core.SCP/Program.cs @@ -113,6 +113,11 @@ builder.Services.AddAutoMapper(automapper => //EF ORM QueryWithNoLock builder.Services.AddEFSetup(_configuration); +builder.Services.AddMediator(cfg => +{ + +}); + //转发头设置 获取真实IP builder.Services.Configure(options => diff --git a/IRC.Core.SCP/Service/OSSService.cs b/IRC.Core.SCP/Service/OSSService.cs index 4af37a247..1ac5e80ee 100644 --- a/IRC.Core.SCP/Service/OSSService.cs +++ b/IRC.Core.SCP/Service/OSSService.cs @@ -1,295 +1,357 @@ -using Aliyun.OSS; -using IRaCIS.Core.Infrastructure; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Options; -using Minio.DataModel.Args; -using Minio; -using SharpCompress.Common; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Security.AccessControl; -using System.Text; -using System.Threading.Tasks; -using System.Runtime.InteropServices; -using System.Text.Json.Serialization; -using Minio.ApiEndpoints; -using System.Reactive.Linq; -using IRaCIS.Core.Domain.Share; -using IRaCIS.Core.Infrastructure.NewtonsoftJson; -using Amazon.Runtime; -using Amazon.SecurityToken; -using Amazon.SecurityToken.Model; +using AlibabaCloud.SDK.Sts20150401; +using Aliyun.OSS; using Amazon; +using Amazon.Runtime; using Amazon.S3; using Amazon.S3.Model; +using Amazon.SecurityToken; +using Amazon.SecurityToken.Model; +using IRaCIS.Core.Infrastructure; +using IRaCIS.Core.Infrastructure.NewtonsoftJson; using MassTransit; -using AlibabaCloud.SDK.Sts20150401; +using Microsoft.Extensions.Options; +using Minio; +using Minio.DataModel.Args; +using System.Reactive.Linq; +using System.Runtime.InteropServices; -namespace IRaCIS.Core.SCP +namespace IRaCIS.Core.SCP; + +#region 绑定和返回模型 + +[LowerCamelCaseJson] +public class MinIOOptions : AWSOptions { - #region 绑定和返回模型 + public int Port { get; set; } - [LowerCamelCaseJson] - public class MinIOOptions : AWSOptions +} + + +public class AWSOptions +{ + public string EndPoint { get; set; } + public bool UseSSL { get; set; } + public string AccessKeyId { get; set; } + public string RoleArn { get; set; } + public string SecretAccessKey { get; set; } + public string BucketName { get; set; } + public string ViewEndpoint { get; set; } + public int DurationSeconds { get; set; } + public string Region { get; set; } +} + +public class AliyunOSSOptions +{ + public string RegionId { get; set; } + public string AccessKeyId { get; set; } + public string AccessKeySecret { get; set; } + + public string InternalEndpoint { get; set; } + + public string EndPoint { get; set; } + public string BucketName { get; set; } + + public string RoleArn { get; set; } + + public string Region { get; set; } + + public string ViewEndpoint { get; set; } + + public int DurationSeconds { get; set; } + + + +} + +public class ObjectStoreServiceOptions +{ + public string ObjectStoreUse { get; set; } + + public AliyunOSSOptions AliyunOSS { get; set; } + + + public MinIOOptions MinIO { get; set; } + + public AWSOptions AWS { get; set; } + +} + +public class ObjectStoreDTO +{ + public string ObjectStoreUse { get; set; } + + + public AliyunOSSTempToken AliyunOSS { get; set; } + + public MinIOOptions MinIO { get; set; } + + public AWSTempToken AWS { get; set; } + +} + +[LowerCamelCaseJson] +public class AliyunOSSTempToken +{ + public string AccessKeyId { get; set; } + public string AccessKeySecret { get; set; } + + public string EndPoint { get; set; } + public string BucketName { get; set; } + + public string Region { get; set; } + + public string ViewEndpoint { get; set; } + + public string SecurityToken { get; set; } + public DateTime Expiration { get; set; } + + +} + +[LowerCamelCaseJson] +public class AWSTempToken +{ + public string Region { get; set; } + public string SessionToken { get; set; } + public string EndPoint { get; set; } + public string AccessKeyId { get; set; } + public string SecretAccessKey { get; set; } + public string BucketName { get; set; } + public string ViewEndpoint { get; set; } + public DateTime Expiration { get; set; } +} + +public enum ObjectStoreUse +{ + AliyunOSS = 0, + MinIO = 1, + AWS = 2, +} + +#endregion + +// aws 参考链接 https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/S3/S3_Basics + +public interface IOSSService +{ + public Task UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true); + public Task UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true); + + public Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath); + + public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; } + + public Task GetSignedUrl(string ossRelativePath); + + public Task DeleteFromPrefix(string prefix); + + public ObjectStoreDTO GetObjectStoreTempToken(); +} + + +public class OSSService : IOSSService +{ + public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; } + + private AliyunOSSTempToken AliyunOSSTempToken { get; set; } + + private AWSTempToken AWSTempToken { get; set; } + + + public OSSService(IOptionsMonitor options) { - public int Port { get; set; } + ObjectStoreServiceOptions = options.CurrentValue; } - public class AWSOptions + + /// + /// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder + /// + /// + /// + /// + /// + /// + public async Task UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true) { - public string EndPoint { get; set; } - public bool UseSSL { get; set; } - public string AccessKeyId { get; set; } - public string RoleArn { get; set; } - public string SecretAccessKey { get; set; } - public string BucketName { get; set; } - public string ViewEndpoint { get; set; } - public int DurationSeconds { get; set; } - public string Region { get; set; } - } + GetObjectStoreTempToken(); - public class AliyunOSSOptions - { - public string RegionId { get; set; } - public string AccessKeyId { get; set; } - public string AccessKeySecret { get; set; } + var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}" : $"{oosFolderPath}/{fileRealName}"; - public string InternalEndpoint { get; set; } - - public string EndPoint { get; set; } - public string BucketName { get; set; } - - public string RoleArn { get; set; } - - public string Region { get; set; } - - public string ViewEndpoint { get; set; } - - public int DurationSeconds { get; set; } - - - - } - - public class ObjectStoreServiceOptions - { - public string ObjectStoreUse { get; set; } - - public AliyunOSSOptions AliyunOSS { get; set; } - - - public MinIOOptions MinIO { get; set; } - - public AWSOptions AWS { get; set; } - - } - - public class ObjectStoreDTO - { - public string ObjectStoreUse { get; set; } - - - public AliyunOSSTempToken AliyunOSS { get; set; } - - public MinIOOptions MinIO { get; set; } - - public AWSTempToken AWS { get; set; } - - } - - [LowerCamelCaseJson] - public class AliyunOSSTempToken - { - public string AccessKeyId { get; set; } - public string AccessKeySecret { get; set; } - - public string EndPoint { get; set; } - public string BucketName { get; set; } - - public string Region { get; set; } - - public string ViewEndpoint { get; set; } - - public string SecurityToken { get; set; } - public DateTime Expiration { get; set; } - - - } - - [LowerCamelCaseJson] - public class AWSTempToken - { - public string Region { get; set; } - public string SessionToken { get; set; } - public string EndPoint { get; set; } - public string AccessKeyId { get; set; } - public string SecretAccessKey { get; set; } - public string BucketName { get; set; } - public string ViewEndpoint { get; set; } - public DateTime Expiration { get; set; } - } - - public enum ObjectStoreUse - { - AliyunOSS = 0, - MinIO = 1, - AWS = 2, - } - - #endregion - - // aws 参考链接 https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/S3/S3_Basics - - public interface IOSSService - { - public Task UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true); - public Task UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true); - - public Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath); - - public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; } - - public Task GetSignedUrl(string ossRelativePath); - - public Task DeleteFromPrefix(string prefix); - - public Task GetObjectStoreTempToken(); - } - - - public class OSSService : IOSSService - { - public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; } - - private AliyunOSSTempToken AliyunOSSTempToken { get; set; } - - private AWSTempToken AWSTempToken { get; set; } - - - public OSSService(IOptionsMonitor options) + try { - ObjectStoreServiceOptions = options.CurrentValue; - - GetObjectStoreTempToken().GetAwaiter().GetResult(); - } - - /// - /// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder - /// - /// - /// - /// - /// - /// - public async Task UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true) - { - var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}" : $"{oosFolderPath}/{fileRealName}"; - - try + using (var memoryStream = new MemoryStream()) { - using (var memoryStream = new MemoryStream()) + fileStream.Seek(0, SeekOrigin.Begin); + + fileStream.CopyTo(memoryStream); + + memoryStream.Seek(0, SeekOrigin.Begin); + + + if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") { - fileStream.Seek(0, SeekOrigin.Begin); + var aliConfig = ObjectStoreServiceOptions.AliyunOSS; - fileStream.CopyTo(memoryStream); - - memoryStream.Seek(0, SeekOrigin.Begin); + var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); - if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") + + // 上传文件 + var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, memoryStream); + + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") + { + var minIOConfig = ObjectStoreServiceOptions.MinIO; + + + var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}") + .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL) + .Build(); + + var putObjectArgs = new PutObjectArgs() + .WithBucket(minIOConfig.BucketName) + .WithObject(ossRelativePath) + .WithStreamData(memoryStream) + .WithObjectSize(memoryStream.Length); + + await minioClient.PutObjectAsync(putObjectArgs); + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") + { + var awsConfig = ObjectStoreServiceOptions.AWS; + + var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken); + + + + //提供awsEndPoint(域名)进行访问配置 + var clientConfig = new AmazonS3Config { - var aliConfig = ObjectStoreServiceOptions.AliyunOSS; + RegionEndpoint = RegionEndpoint.USEast1, + UseHttp = true, + }; - var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); + var amazonS3Client = new AmazonS3Client(credentials, clientConfig); - - - // 上传文件 - var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, memoryStream); - - } - else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") + var putObjectRequest = new Amazon.S3.Model.PutObjectRequest() { - var minIOConfig = ObjectStoreServiceOptions.MinIO; + BucketName = awsConfig.BucketName, + InputStream = memoryStream, + Key = ossRelativePath, + }; - - var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}") - .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL) - .Build(); - - var putObjectArgs = new PutObjectArgs() - .WithBucket(minIOConfig.BucketName) - .WithObject(ossRelativePath) - .WithStreamData(memoryStream) - .WithObjectSize(memoryStream.Length); - - await minioClient.PutObjectAsync(putObjectArgs); - } - else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") - { - var awsConfig = ObjectStoreServiceOptions.AWS; - - var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken); - - - - //提供awsEndPoint(域名)进行访问配置 - var clientConfig = new AmazonS3Config - { - RegionEndpoint = RegionEndpoint.USEast1, - UseHttp = true, - }; - - var amazonS3Client = new AmazonS3Client(credentials, clientConfig); - - var putObjectRequest = new Amazon.S3.Model.PutObjectRequest() - { - BucketName = awsConfig.BucketName, - InputStream = memoryStream, - Key = ossRelativePath, - }; - - await amazonS3Client.PutObjectAsync(putObjectRequest); - } - else - { - throw new BusinessValidationFailedException("未定义的存储介质类型"); - } + await amazonS3Client.PutObjectAsync(putObjectRequest); + } + else + { + throw new BusinessValidationFailedException("未定义的存储介质类型"); } } - catch (Exception ex) - { - - throw new BusinessValidationFailedException($"上传发生异常:{ex.Message}"); - } - - - - - return "/" + ossRelativePath; + } + catch (Exception ex) + { + throw new BusinessValidationFailedException($"上传发生异常:{ex.Message}"); } - /// - /// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder - /// - /// - /// - /// - /// - /// - public async Task UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true) - { - var localFileName = Path.GetFileName(localFilePath); - var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}" : $"{oosFolderPath}/{localFileName}"; + return "/" + ossRelativePath; + + } + + + + /// + /// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder + /// + /// + /// + /// + /// + /// + public async Task UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true) + { + GetObjectStoreTempToken(); + + var localFileName = Path.GetFileName(localFilePath); + + var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}" : $"{oosFolderPath}/{localFileName}"; + + + if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") + { + var aliConfig = ObjectStoreServiceOptions.AliyunOSS; + + var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); + + // 上传文件 + var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, localFilePath); + + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") + { + var minIOConfig = ObjectStoreServiceOptions.MinIO; + + + var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}") + .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL) + .Build(); + + var putObjectArgs = new PutObjectArgs() + .WithBucket(minIOConfig.BucketName) + .WithObject(ossRelativePath) + .WithFileName(localFilePath); + + await minioClient.PutObjectAsync(putObjectArgs); + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") + { + var awsConfig = ObjectStoreServiceOptions.AWS; + + // 提供awsAccessKeyId和awsSecretAccessKey构造凭证 + var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken); + + //提供awsEndPoint(域名)进行访问配置 + var clientConfig = new AmazonS3Config + { + RegionEndpoint = RegionEndpoint.USEast1, + UseHttp = true, + }; + + var amazonS3Client = new AmazonS3Client(credentials, clientConfig); + + var putObjectRequest = new Amazon.S3.Model.PutObjectRequest() + { + BucketName = awsConfig.BucketName, + FilePath = localFilePath, + Key = ossRelativePath, + }; + + await amazonS3Client.PutObjectAsync(putObjectRequest); + + } + else + { + throw new BusinessValidationFailedException("未定义的存储介质类型"); + } + return "/" + ossRelativePath; + + } + + + public async Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath) + { + GetObjectStoreTempToken(); + + ossRelativePath = ossRelativePath.TrimStart('/'); + try + { if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") @@ -299,24 +361,31 @@ namespace IRaCIS.Core.SCP var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); // 上传文件 - var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, localFilePath); + var result = _ossClient.GetObject(aliConfig.BucketName, ossRelativePath); + + // 将下载的文件流保存到本地文件 + using (var fs = File.OpenWrite(localFilePath)) + { + result.Content.CopyTo(fs); + fs.Close(); + } } else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") { var minIOConfig = ObjectStoreServiceOptions.MinIO; - var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}") .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL) .Build(); - var putObjectArgs = new PutObjectArgs() - .WithBucket(minIOConfig.BucketName) - .WithObject(ossRelativePath) - .WithFileName(localFilePath); + var getObjectArgs = new GetObjectArgs() + .WithBucket(minIOConfig.BucketName) + .WithObject(ossRelativePath) + .WithFile(localFilePath); + + await minioClient.GetObjectAsync(getObjectArgs); - await minioClient.PutObjectAsync(putObjectArgs); } else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") { @@ -334,291 +403,87 @@ namespace IRaCIS.Core.SCP var amazonS3Client = new AmazonS3Client(credentials, clientConfig); - var putObjectRequest = new Amazon.S3.Model.PutObjectRequest() + var getObjectArgs = new Amazon.S3.Model.GetObjectRequest() { BucketName = awsConfig.BucketName, - FilePath = localFilePath, Key = ossRelativePath, }; - await amazonS3Client.PutObjectAsync(putObjectRequest); + + await (await amazonS3Client.GetObjectAsync(getObjectArgs)).WriteResponseStreamToFileAsync(localFilePath, true, CancellationToken.None); + } else { throw new BusinessValidationFailedException("未定义的存储介质类型"); } - return "/" + ossRelativePath; + } + catch (Exception ex) + { + throw new BusinessValidationFailedException("oss下载失败!" + ex.Message); } - public async Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath) + + + + } + + public async Task GetSignedUrl(string ossRelativePath) + { + GetObjectStoreTempToken(); + + ossRelativePath = ossRelativePath.TrimStart('/'); + try { - ossRelativePath = ossRelativePath.TrimStart('/'); - try - { - - if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") - { - var aliConfig = ObjectStoreServiceOptions.AliyunOSS; - - var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); - - // 上传文件 - var result = _ossClient.GetObject(aliConfig.BucketName, ossRelativePath); - - // 将下载的文件流保存到本地文件 - using (var fs = File.OpenWrite(localFilePath)) - { - result.Content.CopyTo(fs); - fs.Close(); - } - - } - else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") - { - var minIOConfig = ObjectStoreServiceOptions.MinIO; - - var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}") - .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL) - .Build(); - - var getObjectArgs = new GetObjectArgs() - .WithBucket(minIOConfig.BucketName) - .WithObject(ossRelativePath) - .WithFile(localFilePath); - - await minioClient.GetObjectAsync(getObjectArgs); - - } - else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") - { - var awsConfig = ObjectStoreServiceOptions.AWS; - - // 提供awsAccessKeyId和awsSecretAccessKey构造凭证 - var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken); - - //提供awsEndPoint(域名)进行访问配置 - var clientConfig = new AmazonS3Config - { - RegionEndpoint = RegionEndpoint.USEast1, - UseHttp = true, - }; - - var amazonS3Client = new AmazonS3Client(credentials, clientConfig); - - var getObjectArgs = new Amazon.S3.Model.GetObjectRequest() - { - BucketName = awsConfig.BucketName, - Key = ossRelativePath, - }; - - - await (await amazonS3Client.GetObjectAsync(getObjectArgs)).WriteResponseStreamToFileAsync(localFilePath, true, CancellationToken.None); - - - } - else - { - throw new BusinessValidationFailedException("未定义的存储介质类型"); - } - } - catch (Exception ex) - { - - throw new BusinessValidationFailedException("oss下载失败!" + ex.Message); - } - - - - - - } - - public async Task GetSignedUrl(string ossRelativePath) - { - ossRelativePath = ossRelativePath.TrimStart('/'); - try - { - - - if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") - { - var aliConfig = ObjectStoreServiceOptions.AliyunOSS; - - var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); - - // 生成签名URL。 - var req = new GeneratePresignedUriRequest(aliConfig.BucketName, ossRelativePath, SignHttpMethod.Get) - { - // 设置签名URL过期时间,默认值为3600秒。 - Expiration = DateTime.Now.AddHours(1), - }; - var uri = _ossClient.GeneratePresignedUri(req); - - return uri.PathAndQuery; - - } - else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") - { - var minIOConfig = ObjectStoreServiceOptions.MinIO; - - var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}") - .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL) - .Build(); - - - var args = new PresignedGetObjectArgs() - .WithBucket(minIOConfig.BucketName) - .WithObject(ossRelativePath) - .WithExpiry(3600) - /*.WithHeaders(reqParams)*/; - - var presignedUrl = await minioClient.PresignedGetObjectAsync(args); - - Uri uri = new Uri(presignedUrl); - - string relativePath = uri.PathAndQuery; - - - return relativePath; - - } - else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") - { - var awsConfig = ObjectStoreServiceOptions.AWS; - - - // 提供awsAccessKeyId和awsSecretAccessKey构造凭证 - var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken); - - //提供awsEndPoint(域名)进行访问配置 - var clientConfig = new AmazonS3Config - { - RegionEndpoint = RegionEndpoint.USEast1, - UseHttp = true, - }; - - var amazonS3Client = new AmazonS3Client(credentials, clientConfig); - - var presignedUrl = await amazonS3Client.GetPreSignedURLAsync(new GetPreSignedUrlRequest() - { - BucketName = awsConfig.BucketName, - Key = ossRelativePath, - Expires = DateTime.UtcNow.AddMinutes(120) - }); - - Uri uri = new Uri(presignedUrl); - - string relativePath = uri.PathAndQuery; - - - return relativePath; - } - else - { - throw new BusinessValidationFailedException("未定义的存储介质类型"); - } - } - catch (Exception ex) - { - - throw new BusinessValidationFailedException("oss授权url失败!" + ex.Message); - } - - } - - /// - /// 删除某个目录的文件 - /// - /// - /// - public async Task DeleteFromPrefix(string prefix) - { if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") { var aliConfig = ObjectStoreServiceOptions.AliyunOSS; var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); - - try + // 生成签名URL。 + var req = new GeneratePresignedUriRequest(aliConfig.BucketName, ossRelativePath, SignHttpMethod.Get) { - ObjectListing objectListing = null; - string nextMarker = null; - do - { - // 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker - objectListing = _ossClient.ListObjects(new Aliyun.OSS.ListObjectsRequest(aliConfig.BucketName) - { - Prefix = prefix, - MaxKeys = 1000, - Marker = nextMarker - }); - - List keys = objectListing.ObjectSummaries.Select(t => t.Key).ToList(); - - // 删除获取到的文件 - if (keys.Count > 0) - { - _ossClient.DeleteObjects(new Aliyun.OSS.DeleteObjectsRequest(aliConfig.BucketName, keys, false)); - } - - // 设置 NextMarker 以获取下一页的数据 - nextMarker = objectListing.NextMarker; - - } while (objectListing.IsTruncated); - } - catch (Exception ex) - { - Console.WriteLine($"Error: {ex.Message}"); - } + // 设置签名URL过期时间,默认值为3600秒。 + Expiration = DateTime.Now.AddHours(1), + }; + var uri = _ossClient.GeneratePresignedUri(req); + return uri.PathAndQuery; } else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") { var minIOConfig = ObjectStoreServiceOptions.MinIO; - var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}") .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL) .Build(); - var listArgs = new ListObjectsArgs().WithBucket(minIOConfig.BucketName).WithPrefix(prefix).WithRecursive(true); - - - - // 创建一个空列表用于存储对象键 - var objects = new List(); - - // 使用 await foreach 来异步迭代对象列表 - await foreach (var item in minioClient.ListObjectsEnumAsync(listArgs)) - { - objects.Add(item.Key); - } - - - if (objects.Count > 0) - { - var objArgs = new RemoveObjectsArgs() - .WithBucket(minIOConfig.BucketName) - .WithObjects(objects); - - // 删除对象 - await minioClient.RemoveObjectsAsync(objArgs); - } + var args = new PresignedGetObjectArgs() + .WithBucket(minIOConfig.BucketName) + .WithObject(ossRelativePath) + .WithExpiry(3600) + /*.WithHeaders(reqParams)*/; + + var presignedUrl = await minioClient.PresignedGetObjectAsync(args); + + Uri uri = new Uri(presignedUrl); + + string relativePath = uri.PathAndQuery; + return relativePath; } else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") { - var awsConfig = ObjectStoreServiceOptions.AWS; @@ -634,144 +499,272 @@ namespace IRaCIS.Core.SCP var amazonS3Client = new AmazonS3Client(credentials, clientConfig); - // 列出指定前缀下的所有对象 - var listObjectsRequest = new ListObjectsV2Request + var presignedUrl = await amazonS3Client.GetPreSignedURLAsync(new GetPreSignedUrlRequest() { BucketName = awsConfig.BucketName, - Prefix = prefix - }; + Key = ossRelativePath, + Expires = DateTime.UtcNow.AddMinutes(120) + }); - var listObjectsResponse = await amazonS3Client.ListObjectsV2Async(listObjectsRequest); - - if (listObjectsResponse.S3Objects.Count > 0) - { - // 准备删除请求 - var deleteObjectsRequest = new Amazon.S3.Model.DeleteObjectsRequest - { - BucketName = awsConfig.BucketName, - Objects = new List() - }; - - foreach (var s3Object in listObjectsResponse.S3Objects) - { - deleteObjectsRequest.Objects.Add(new KeyVersion - { - Key = s3Object.Key - }); - } - - // 批量删除对象 - var deleteObjectsResponse = await amazonS3Client.DeleteObjectsAsync(deleteObjectsRequest); - } + Uri uri = new Uri(presignedUrl); + string relativePath = uri.PathAndQuery; + return relativePath; } else { throw new BusinessValidationFailedException("未定义的存储介质类型"); } } - - - - - public async Task GetObjectStoreTempToken() + catch (Exception ex) { - var ossOptions = ObjectStoreServiceOptions.AliyunOSS; - if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") - { - var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config() - { - AccessKeyId = ossOptions.AccessKeyId, - AccessKeySecret = ossOptions.AccessKeySecret, - //AccessKeyId = "LTAI5tJV76pYX5yPg1N9QVE8", - //AccessKeySecret = "roRNLa9YG1of4pYruJGCNKBXEWTAWa", - - Endpoint = "sts.cn-hangzhou.aliyuncs.com" - }); - - var assumeRoleRequest = new AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleRequest(); - // 将设置为自定义的会话名称,例如oss-role-session。 - assumeRoleRequest.RoleSessionName = $"session-name-{NewId.NextGuid()}"; - // 将替换为拥有上传文件到指定OSS Bucket权限的RAM角色的ARN。 - assumeRoleRequest.RoleArn = ossOptions.RoleArn; - //assumeRoleRequest.RoleArn = "acs:ram::1899121822495495:role/webdirect"; - assumeRoleRequest.DurationSeconds = ossOptions.DurationSeconds; - var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions(); - var response = client.AssumeRoleWithOptions(assumeRoleRequest, runtime); - var credentials = response.Body.Credentials; - - var tempToken = new AliyunOSSTempToken() - { - AccessKeyId = credentials.AccessKeyId, - AccessKeySecret = credentials.AccessKeySecret, - - //转为服务器时区,最后统一转为客户端时区 - Expiration = TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse(credentials.Expiration), TimeZoneInfo.Local), - SecurityToken = credentials.SecurityToken, - - - Region = ossOptions.Region, - BucketName = ossOptions.BucketName, - EndPoint = ossOptions.EndPoint, - ViewEndpoint = ossOptions.ViewEndpoint, - - }; - - AliyunOSSTempToken = tempToken; - - return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AliyunOSS = tempToken }; - } - else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") - { - return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, MinIO = ObjectStoreServiceOptions.MinIO }; - } - else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") - { - var awsOptions = ObjectStoreServiceOptions.AWS; - - //aws 临时凭证 - // 创建 STS 客户端 - var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey); - - // 使用 AssumeRole 请求临时凭证 - var assumeRoleRequest = new AssumeRoleRequest - { - - RoleArn = awsOptions.RoleArn, // 角色 ARN - RoleSessionName = $"session-name-{NewId.NextGuid()}", - DurationSeconds = awsOptions.DurationSeconds // 临时凭证有效期 - }; - - var assumeRoleResponse = await stsClient.AssumeRoleAsync(assumeRoleRequest); - - var credentials = assumeRoleResponse.Credentials; - - var tempToken = new AWSTempToken() - { - AccessKeyId = credentials.AccessKeyId, - SecretAccessKey = credentials.SecretAccessKey, - SessionToken = credentials.SessionToken, - Expiration = credentials.Expiration, - Region = awsOptions.Region, - BucketName = awsOptions.BucketName, - EndPoint = awsOptions.EndPoint, - ViewEndpoint = awsOptions.ViewEndpoint, - - }; - - AWSTempToken = tempToken; - return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AWS = tempToken }; - } - else - { - throw new BusinessValidationFailedException("未定义的存储介质类型"); - } + throw new BusinessValidationFailedException("oss授权url失败!" + ex.Message); } } + /// + /// 删除某个目录的文件 + /// + /// + /// + public async Task DeleteFromPrefix(string prefix) + { + GetObjectStoreTempToken(); + + if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") + { + var aliConfig = ObjectStoreServiceOptions.AliyunOSS; + + var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); + + + try + { + ObjectListing objectListing = null; + string nextMarker = null; + do + { + // 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker + objectListing = _ossClient.ListObjects(new Aliyun.OSS.ListObjectsRequest(aliConfig.BucketName) + { + Prefix = prefix, + MaxKeys = 1000, + Marker = nextMarker + }); + + List keys = objectListing.ObjectSummaries.Select(t => t.Key).ToList(); + + // 删除获取到的文件 + if (keys.Count > 0) + { + _ossClient.DeleteObjects(new Aliyun.OSS.DeleteObjectsRequest(aliConfig.BucketName, keys, false)); + } + + // 设置 NextMarker 以获取下一页的数据 + nextMarker = objectListing.NextMarker; + + } while (objectListing.IsTruncated); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + + + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") + { + var minIOConfig = ObjectStoreServiceOptions.MinIO; + + + var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}") + .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL) + .Build(); + + + var listArgs = new ListObjectsArgs().WithBucket(minIOConfig.BucketName).WithPrefix(prefix).WithRecursive(true); + + + + // 创建一个空列表用于存储对象键 + var objects = new List(); + + // 使用 await foreach 来异步迭代对象列表 + await foreach (var item in minioClient.ListObjectsEnumAsync(listArgs)) + { + objects.Add(item.Key); + } + + + if (objects.Count > 0) + { + var objArgs = new RemoveObjectsArgs() + .WithBucket(minIOConfig.BucketName) + .WithObjects(objects); + + // 删除对象 + await minioClient.RemoveObjectsAsync(objArgs); + } + + + + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") + { + + var awsConfig = ObjectStoreServiceOptions.AWS; + + + // 提供awsAccessKeyId和awsSecretAccessKey构造凭证 + var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken); + + //提供awsEndPoint(域名)进行访问配置 + var clientConfig = new AmazonS3Config + { + RegionEndpoint = RegionEndpoint.USEast1, + UseHttp = true, + }; + + var amazonS3Client = new AmazonS3Client(credentials, clientConfig); + + // 列出指定前缀下的所有对象 + var listObjectsRequest = new ListObjectsV2Request + { + BucketName = awsConfig.BucketName, + Prefix = prefix + }; + + var listObjectsResponse = await amazonS3Client.ListObjectsV2Async(listObjectsRequest); + + if (listObjectsResponse.S3Objects.Count > 0) + { + // 准备删除请求 + var deleteObjectsRequest = new Amazon.S3.Model.DeleteObjectsRequest + { + BucketName = awsConfig.BucketName, + Objects = new List() + }; + + foreach (var s3Object in listObjectsResponse.S3Objects) + { + deleteObjectsRequest.Objects.Add(new KeyVersion + { + Key = s3Object.Key + }); + } + + // 批量删除对象 + var deleteObjectsResponse = await amazonS3Client.DeleteObjectsAsync(deleteObjectsRequest); + } + + + + } + else + { + throw new BusinessValidationFailedException("未定义的存储介质类型"); + } + } + + + public ObjectStoreDTO GetObjectStoreTempToken() + { + + var ossOptions = ObjectStoreServiceOptions.AliyunOSS; + + if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") + { + var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config() + { + AccessKeyId = ossOptions.AccessKeyId, + AccessKeySecret = ossOptions.AccessKeySecret, + //AccessKeyId = "LTAI5tJV76pYX5yPg1N9QVE8", + //AccessKeySecret = "roRNLa9YG1of4pYruJGCNKBXEWTAWa", + + Endpoint = "sts.cn-hangzhou.aliyuncs.com" + }); + + var assumeRoleRequest = new AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleRequest(); + // 将设置为自定义的会话名称,例如oss-role-session。 + assumeRoleRequest.RoleSessionName = $"session-name-{NewId.NextGuid()}"; + // 将替换为拥有上传文件到指定OSS Bucket权限的RAM角色的ARN。 + assumeRoleRequest.RoleArn = ossOptions.RoleArn; + //assumeRoleRequest.RoleArn = "acs:ram::1899121822495495:role/webdirect"; + assumeRoleRequest.DurationSeconds = ossOptions.DurationSeconds; + var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions(); + var response = client.AssumeRoleWithOptions(assumeRoleRequest, runtime); + var credentials = response.Body.Credentials; + + var tempToken = new AliyunOSSTempToken() + { + AccessKeyId = credentials.AccessKeyId, + AccessKeySecret = credentials.AccessKeySecret, + + //转为服务器时区,最后统一转为客户端时区 + Expiration = TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse(credentials.Expiration), TimeZoneInfo.Local), + SecurityToken = credentials.SecurityToken, + + + Region = ossOptions.Region, + BucketName = ossOptions.BucketName, + EndPoint = ossOptions.EndPoint, + ViewEndpoint = ossOptions.ViewEndpoint, + + }; + + AliyunOSSTempToken = tempToken; + + return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AliyunOSS = tempToken }; + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO") + { + return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, MinIO = ObjectStoreServiceOptions.MinIO }; + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") + { + var awsOptions = ObjectStoreServiceOptions.AWS; + + //aws 临时凭证 + // 创建 STS 客户端 + var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey); + + // 使用 AssumeRole 请求临时凭证 + var assumeRoleRequest = new AssumeRoleRequest + { + + RoleArn = awsOptions.RoleArn, // 角色 ARN + RoleSessionName = $"session-name-{NewId.NextGuid()}", + DurationSeconds = awsOptions.DurationSeconds // 临时凭证有效期 + }; + + var assumeRoleResponse = stsClient.AssumeRoleAsync(assumeRoleRequest).Result; + + var credentials = assumeRoleResponse.Credentials; + + var tempToken = new AWSTempToken() + { + AccessKeyId = credentials.AccessKeyId, + SecretAccessKey = credentials.SecretAccessKey, + SessionToken = credentials.SessionToken, + Expiration = credentials.Expiration, + Region = awsOptions.Region, + BucketName = awsOptions.BucketName, + EndPoint = awsOptions.EndPoint, + ViewEndpoint = awsOptions.ViewEndpoint, + + }; + + AWSTempToken = tempToken; + return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AWS = tempToken }; + } + else + { + throw new BusinessValidationFailedException("未定义的存储介质类型"); + } + } } diff --git a/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs b/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs index 97e63a161..00134e738 100644 --- a/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs +++ b/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs @@ -456,7 +456,9 @@ namespace IRaCIS.Core.Application.Services if (taskInfo.TaskStudyCount > 0) { - var taskStudyList = await _taskStudyRepository.Where(t => t.TrialId == indto.TrialId && t.VisitTaskId == indto.VisitTaskId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); + var taskStudyList = await _taskStudyRepository.Where(t => t.TrialId == indto.TrialId && t.VisitTaskId == indto.VisitTaskId) + .WhereIf(taskInfo.IsImageFilter == true, t => ("|" + taskInfo.CriterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|")) + .ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); foreach (var study in taskStudyList) { @@ -484,7 +486,7 @@ namespace IRaCIS.Core.Application.Services var isManualGenerate = await _trialReadingCriterionRepository.AnyAsync(t => t.Id == taskInfo.TrialReadingCriterionId && t.IsAutoCreate == false); var dicomStudyList = await _dicomStudyRepository.Where(t => t.TrialId == indto.TrialId && t.SubjectVisitId == indto.SujectVisitId) - .WhereIf(taskInfo.IsImageFilter == true, t => taskInfo.CriterionModalitys.Contains(t.ModalityForEdit)) + .WhereIf(taskInfo.IsImageFilter == true, t => ("|" + taskInfo.CriterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|")) .WhereIf(isManualGenerate, t => t.SubjectCriteriaEvaluationVisitStudyFilterList.Any(t => t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId && t.IsConfirmed && t.IsReading)) .Select(k => new VisitStudyDTO() { diff --git a/IRaCIS.Core.Domain/Image/DicomInstance.cs b/IRaCIS.Core.Domain/Image/DicomInstance.cs index 393f1fa84..a6c22faa3 100644 --- a/IRaCIS.Core.Domain/Image/DicomInstance.cs +++ b/IRaCIS.Core.Domain/Image/DicomInstance.cs @@ -12,6 +12,9 @@ public class DicomInstance : BaseFullAuditEntity, IEntitySeqId [JsonIgnore] [ForeignKey("StudyId")] public DicomStudy DicomStudy { get; set; } + + [JsonIgnore] + public List ReadingTableAnswerRowInfoList { get; set; } #endregion public bool Anonymize { get; set; } diff --git a/IRaCIS.Core.Domain/Reading/AdditionalEvaluate/SubjectCriteriaEvaluationVisitStudyFilter.cs b/IRaCIS.Core.Domain/Reading/AdditionalEvaluate/SubjectCriteriaEvaluationVisitStudyFilter.cs index 39855f498..63e7e46ee 100644 --- a/IRaCIS.Core.Domain/Reading/AdditionalEvaluate/SubjectCriteriaEvaluationVisitStudyFilter.cs +++ b/IRaCIS.Core.Domain/Reading/AdditionalEvaluate/SubjectCriteriaEvaluationVisitStudyFilter.cs @@ -15,6 +15,7 @@ public class SubjectCriteriaEvaluationVisitStudyFilter : BaseFullAuditEntity [ForeignKey("SeriesId")] [JsonIgnore] public DicomSeries Series { get; set; } + [ForeignKey("StudyId")] [JsonIgnore] public DicomStudy Study { get; set; } diff --git a/IRaCIS.Core.Infra.EFCore/EntityConfigration/ImageConfigration.cs b/IRaCIS.Core.Infra.EFCore/EntityConfigration/ImageConfigration.cs index 22cdb7da9..873e12540 100644 --- a/IRaCIS.Core.Infra.EFCore/EntityConfigration/ImageConfigration.cs +++ b/IRaCIS.Core.Infra.EFCore/EntityConfigration/ImageConfigration.cs @@ -13,9 +13,11 @@ public class DicomStudyConfigration : IEntityTypeConfiguration { builder.HasKey(e => e.SeqId); - builder.HasMany(s => s.SeriesList).WithOne(se => se.DicomStudy).HasForeignKey(se => se.StudyId).HasPrincipalKey(st=>st.Id); + builder.HasMany(s => s.SeriesList).WithOne(se => se.DicomStudy).HasForeignKey(se => se.StudyId).HasPrincipalKey(st => st.Id); builder.HasMany(s => s.DicomStudyMonitorList).WithOne(sm => sm.DicomStudy).HasForeignKey(sm => sm.StudyId).HasPrincipalKey(se => se.Id); + + builder.HasMany(s => s.SubjectCriteriaEvaluationVisitStudyFilterList).WithOne(sm => sm.Study).HasForeignKey(sm => sm.StudyId).HasPrincipalKey(se => se.Id); } } @@ -27,6 +29,8 @@ public class DicomSeriesConfigration : IEntityTypeConfiguration builder.HasMany(s => s.DicomInstanceList).WithOne(di => di.DicomSerie).HasForeignKey(t => t.SeriesId).HasPrincipalKey(se => se.Id); + builder.HasMany(s => s.SubjectCriteriaEvaluationVisitStudyFilterList).WithOne(di => di.Series).HasForeignKey(t => t.SeriesId).HasPrincipalKey(se => se.Id); + } } @@ -35,6 +39,9 @@ public class DicomInstanceConfigration : IEntityTypeConfiguration public void Configure(EntityTypeBuilder builder) { builder.HasKey(e => e.SeqId); + + builder.HasMany(s => s.ReadingTableAnswerRowInfoList).WithOne(di => di.Instance).HasForeignKey(t => t.InstanceId).HasPrincipalKey(se => se.Id); + } } @@ -95,3 +102,8 @@ public class SCPInstanceConfigration : IEntityTypeConfiguration builder.HasKey(e => e.SeqId); } } + + + + +