From abb9f47646d7389a33eb636de9e94457ca29afbe Mon Sep 17 00:00:00 2001
From: he <109787524@qq.com>
Date: Fri, 28 Nov 2025 11:36:47 +0800
Subject: [PATCH] =?UTF-8?q?=E9=82=AE=E4=BB=B6=E4=B8=B4=E6=97=B6=E4=BF=AE?=
=?UTF-8?q?=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../IRaCIS.Core.Application.xml | 47 +
.../Service/Common/EmailLogService.cs | 357 +-
IRaCIS.Core.Domain/Common/EmailLog.cs | 3 +
...251128033532_EmailErrorMessage.Designer.cs | 21270 ++++++++++++++++
.../20251128033532_EmailErrorMessage.cs | 30 +
.../IRaCISDBContextModelSnapshot.cs | 5 +
6 files changed, 21696 insertions(+), 16 deletions(-)
create mode 100644 IRaCIS.Core.Infra.EFCore/Migrations/20251128033532_EmailErrorMessage.Designer.cs
create mode 100644 IRaCIS.Core.Infra.EFCore/Migrations/20251128033532_EmailErrorMessage.cs
diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
index 2fbc18fdc..a4f3f9bd7 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
@@ -1353,6 +1353,48 @@
+
+
+ 处理收件箱中的邮件发送失败通知
+
+
+
+
+
+ 从失败通知邮件中提取原始邮件的Message-Id
+
+
+
+
+
+
+ 从失败通知邮件中提取错误信息
+
+
+
+
+
+
+ 获取邮件内容摘要(前200个字符)
+
+
+
+
+
+
+ 通过收件人信息处理失败通知邮件
+
+
+
+
+
+
+ 判断失败通知邮件是否与指定的EmailLog相关
+
+
+
+
+
邮件筛选条件构建
@@ -9187,6 +9229,11 @@
任务Id
+
+
+ 单位
+
+
保存表格问题标记
diff --git a/IRaCIS.Core.Application/Service/Common/EmailLogService.cs b/IRaCIS.Core.Application/Service/Common/EmailLogService.cs
index 5dde4bd97..eadb95954 100644
--- a/IRaCIS.Core.Application/Service/Common/EmailLogService.cs
+++ b/IRaCIS.Core.Application/Service/Common/EmailLogService.cs
@@ -234,12 +234,12 @@ public class EmailLogService(IRepository _emailLogRepository,
[HttpPost]
public async Task SynchronizationEmail()
{
-
- var maxTime=await _emailLogRepository.MaxAsync(t => t.EmailDate);
-
+ var maxTime = await _emailLogRepository.MaxAsync(t => t.EmailDate);
+ var startDate = maxTime ?? DateTime.MinValue;
List emailList = new List();
List EmailRecipientLogList = new List();
+ // 第一步:同步发件箱邮件
using (var client = new ImapClient())
{
try
@@ -248,18 +248,13 @@ public class EmailLogService(IRepository _emailLogRepository,
AuthenticateImap(client);
var sentFolder = OpenSentFolder(client);
- var startDate = maxTime ?? DateTime.MinValue;
var searchQuery = SearchQuery.All.And(SearchQuery.DeliveredAfter(startDate));
var uids = sentFolder.Search(searchQuery).ToList();
-
foreach (var uid in uids)
{
try
{
- //var message = sentFolder.GetMessage(uid);
- // var emailView = ConvertToEmailLogView(uid, message);
-
var message = sentFolder.GetMessage(uid);
if (message.Date.DateTime <= startDate)
{
@@ -267,7 +262,7 @@ public class EmailLogService(IRepository _emailLogRepository,
}
var emaillog = new EmailLog
{
- Id=NewId.NextGuid(),
+ Id = NewId.NextGuid(),
UniqueId = uid.ToString(),
MessageId = message.MessageId ?? string.Empty,
EmailSubject = message.Subject ?? string.Empty,
@@ -282,7 +277,7 @@ public class EmailLogService(IRepository _emailLogRepository,
emaillog.SenderName = fromMailbox.Name ?? string.Empty;
}
- List recipientLogs= new List();
+ List recipientLogs = new List();
int sort = 0;
message.To.Mailboxes.ForEach(x =>
@@ -318,22 +313,37 @@ public class EmailLogService(IRepository _emailLogRepository,
}
}
-
sentFolder.Close();
}
catch (Exception ex)
{
+ Console.WriteLine($"同步发件箱邮件时出错: {ex.Message}");
}
finally
{
client.Disconnect(true);
}
-
- await _emailLogRepository.AddRangeAsync(emailList);
- await _emailRecipientLogRepository.AddRangeAsync(EmailRecipientLogList);
- await _emailLogRepository.SaveChangesAsync();
- return ResponseOutput.Ok();
}
+
+ // 保存同步的发件箱邮件
+ await _emailLogRepository.AddRangeAsync(emailList);
+ await _emailRecipientLogRepository.AddRangeAsync(EmailRecipientLogList);
+ await _emailLogRepository.SaveChangesAsync();
+
+ // 第二步:处理收件箱中的邮件发送失败通知
+ try
+ {
+ await ProcessInboxFailureNotifications();
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"处理收件箱失败通知邮件时出错: {ex.Message}");
+ Console.WriteLine($"异常堆栈: {ex.StackTrace}");
+ // 即使处理失败通知邮件出错,也不影响整体同步操作的成功
+ // 记录警告但不中断主流程
+ }
+
+ return ResponseOutput.Ok();
}
private IMailFolder OpenSentFolder(ImapClient client)
@@ -391,6 +401,60 @@ public class EmailLogService(IRepository _emailLogRepository,
return folder;
}
+ private IMailFolder OpenInboxFolder(ImapClient client)
+ {
+ IMailFolder folder = null;
+ try
+ {
+ folder = client.GetFolder(SpecialFolder.All);
+ }
+ catch { }
+
+ if (folder == null)
+ {
+ var candidates = new[] { "收件箱", "Inbox" };
+ foreach (var name in candidates)
+ {
+ try
+ {
+ var f = client.GetFolder(name);
+ if (f != null)
+ {
+ folder = f;
+ break;
+ }
+ }
+ catch { }
+ }
+ }
+
+ if (folder == null)
+ {
+ try
+ {
+ var personal = client.GetFolder(client.PersonalNamespaces.FirstOrDefault());
+ if (personal != null)
+ {
+ foreach (var sub in personal.GetSubfolders(false))
+ {
+ if (string.Equals(sub.FullName, "Inbox", StringComparison.OrdinalIgnoreCase))
+ {
+ folder = sub;
+ break;
+ }
+ }
+ }
+ }
+ catch { }
+ }
+
+ if (folder == null)
+ throw new InvalidOperationException("未找到收件箱文件夹");
+
+ folder.Open(FolderAccess.ReadOnly);
+ return folder;
+ }
+
private void AuthenticateImap(ImapClient client)
{
try
@@ -420,6 +484,267 @@ public class EmailLogService(IRepository _emailLogRepository,
}
}
+ ///
+ /// 处理收件箱中的邮件发送失败通知
+ ///
+ ///
+ private async Task ProcessInboxFailureNotifications()
+ {
+ using (var client = new ImapClient())
+ {
+ try
+ {
+ client.Connect(_systemEmailConfig.Imap, 993, SecureSocketOptions.SslOnConnect);
+ AuthenticateImap(client);
+ var inboxFolder = OpenInboxFolder(client);
+
+ // 搜索可能包含失败通知的邮件
+ // 通常失败通知邮件会包含"失败"、"错误"、"undeliverable"、"delivery failed"等关键词
+ var searchQuery = SearchQuery.All.Or(SearchQuery.SubjectContains("失败"))
+ .Or(SearchQuery.SubjectContains("错误"))
+ .Or(SearchQuery.SubjectContains("undeliverable"))
+ .Or(SearchQuery.SubjectContains("delivery failed"))
+ .Or(SearchQuery.SubjectContains("Delivery Status Notification"))
+ .Or(SearchQuery.BodyContains("失败"))
+ .Or(SearchQuery.BodyContains("错误"))
+ .Or(SearchQuery.BodyContains("undeliverable"))
+ .Or(SearchQuery.BodyContains("delivery failed")).And(SearchQuery.DeliveredAfter(DateTime.Parse("2025-11-27")));
+
+ var uids = inboxFolder.Search(searchQuery).ToList();
+ var processedCount = 0;
+ var updatedCount = 0;
+
+ foreach (var uid in uids)
+ {
+ try
+ {
+ var message = inboxFolder.GetMessage(uid);
+
+ // 尝试从邮件内容中提取原始邮件的Message-Id或相关信息
+ var originalMessageId = ExtractOriginalMessageId(message);
+ if (!string.IsNullOrEmpty(originalMessageId))
+ {
+ // 查找对应的EmailLog记录
+ var emailLog = await _emailLogRepository
+ .Where(x => x.MessageId == originalMessageId)
+ .FirstOrDefaultAsync();
+
+ if (emailLog != null && emailLog.EmailStateEnum == EmailState.Success)
+ {
+ // 提取错误信息
+ var errorMessage = ExtractErrorMessage(message);
+
+ // 更新邮件状态为失败
+ emailLog.EmailStateEnum = EmailState.Error;
+ emailLog.ErrorMessage = errorMessage ?? "邮件发送失败,具体原因未知";
+
+ //await _emailLogRepository.UpdateAsync(emailLog);
+ updatedCount++;
+ }
+ }
+ else
+ {
+ // 如果无法从Message-Id匹配,尝试从邮件内容中提取收件人信息进行匹配
+ await ProcessFailureNotificationByRecipient(message);
+ }
+ processedCount++;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"处理收件箱邮件 UID:{uid} 失败: {ex.Message}");
+ // 记录详细异常信息用于调试
+ Console.WriteLine($"异常堆栈: {ex.StackTrace}");
+ }
+ }
+
+ Console.WriteLine($"收件箱失败通知邮件处理完成: 共处理 {processedCount} 封邮件,更新 {updatedCount} 条记录");
+ inboxFolder.Close();
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"连接收件箱处理失败通知邮件时出错: {ex.Message}");
+ Console.WriteLine($"异常堆栈: {ex.StackTrace}");
+ throw; // 重新抛出异常,让上层调用者决定如何处理
+ }
+ finally
+ {
+ try
+ {
+ client.Disconnect(true);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"断开IMAP客户端连接时出错: {ex.Message}");
+ }
+ }
+ }
+ }
+
+ ///
+ /// 从失败通知邮件中提取原始邮件的Message-Id
+ ///
+ ///
+ ///
+ private string ExtractOriginalMessageId(MimeMessage message)
+ {
+ // 首先检查邮件头中是否有原始Message-Id
+ var originalMessageId = message.Headers["Original-Message-ID"] ??
+ message.Headers["X-Original-Message-ID"] ??
+ message.Headers["In-Reply-To"];
+
+ if (!string.IsNullOrEmpty(originalMessageId))
+ {
+ // 清理Message-Id格式(移除尖括号)
+ originalMessageId = originalMessageId.Trim('<', '>');
+ return originalMessageId;
+ }
+
+ // 如果邮件头中没有,尝试从邮件正文中提取
+ var content = message.HtmlBody ?? message.TextBody ?? string.Empty;
+
+ // 尝试匹配常见的Message-Id格式
+ var messageIdPattern = @"(?:Message-ID|Message-Id|message-id):\s*([^>\s]+)>?";
+ var match = System.Text.RegularExpressions.Regex.Match(content, messageIdPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
+ if (match.Success)
+ {
+ return match.Groups[1].Value;
+ }
+
+ // 尝试从邮件引用部分提取
+ var referencePattern = @"^>.*Message-ID:\s*([^>\s]+)>?";
+ var matches = System.Text.RegularExpressions.Regex.Matches(content, referencePattern, System.Text.RegularExpressions.RegexOptions.Multiline | System.Text.RegularExpressions.RegexOptions.IgnoreCase);
+ if (matches.Count > 0)
+ {
+ return matches[0].Groups[1].Value;
+ }
+
+ return null;
+ }
+
+ ///
+ /// 从失败通知邮件中提取错误信息
+ ///
+ ///
+ ///
+ private string ExtractErrorMessage(MimeMessage message)
+ {
+ var content = message.HtmlBody ?? message.TextBody ?? string.Empty;
+
+ // 尝试提取具体的错误信息
+ // 常见的错误信息模式
+ var errorPatterns = new[]
+ {
+ @"(?i)reason\s*:\s*([^\r\n]+)",
+ @"(?i)error\s*:\s*([^\r\n]+)",
+ @"(?i)failure\s*:\s*([^\r\n]+)",
+ @"(?i)诊断信息[::]\s*([^\r\n]+)",
+ @"(?i)错误详情[::]\s*([^\r\n]+)",
+ @"(?i)Technical details of permanent failure[::]\s*([^\r\n]+)",
+ @"(?i)The error that the other server returned was[::]\s*([^\r\n]+)"
+ };
+
+ foreach (var pattern in errorPatterns)
+ {
+ var match = System.Text.RegularExpressions.Regex.Match(content, pattern);
+ if (match.Success)
+ {
+ return match.Groups[1].Value.Trim();
+ }
+ }
+
+ // 如果没有找到具体的错误信息,返回邮件主题和部分内容
+ return $"主题: {message.Subject}\n内容摘要: {GetContentSummary(content)}";
+ }
+
+ ///
+ /// 获取邮件内容摘要(前200个字符)
+ ///
+ ///
+ ///
+ private string GetContentSummary(string content)
+ {
+ if (string.IsNullOrEmpty(content))
+ return string.Empty;
+
+ // 移除HTML标签
+ var plainText = System.Text.RegularExpressions.Regex.Replace(content, @"<[^>]+>", string.Empty);
+ plainText = System.Text.RegularExpressions.Regex.Replace(plainText, @"\s+", " ");
+
+ return plainText.Length > 200 ? plainText.Substring(0, 200) + "..." : plainText;
+ }
+
+ ///
+ /// 通过收件人信息处理失败通知邮件
+ ///
+ ///
+ ///
+ private async Task ProcessFailureNotificationByRecipient(MimeMessage message)
+ {
+ var content = message.HtmlBody ?? message.TextBody ?? string.Empty;
+
+ // 尝试从邮件内容中提取原始收件人地址
+ var recipientPattern = @"(?:to|To|收件人)[::]\s*([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})";
+ var match = System.Text.RegularExpressions.Regex.Match(content, recipientPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
+
+ if (match.Success)
+ {
+ var recipientEmail = match.Groups[1].Value;
+
+ // 查找最近发送给该收件人的邮件
+ var recentEmailLogs = await _emailLogRepository
+ .Where(x => x.EmailRecipientLogList.Any(r => r.RecipientAddress == recipientEmail))
+ .Where(x => x.EmailDate >= DateTime.Now.AddDays(-7)) // 最近7天内的邮件
+ .OrderByDescending(x => x.EmailDate)
+ .Take(5) // 取最近的5封
+ .ToListAsync();
+
+ foreach (var emailLog in recentEmailLogs)
+ {
+ if (emailLog.EmailStateEnum == EmailState.Success)
+ {
+ // 检查邮件主题是否匹配(如果失败通知邮件中包含原始主题)
+ if (IsLikelyRelatedEmail(message, emailLog))
+ {
+ var errorMessage = ExtractErrorMessage(message);
+ emailLog.EmailStateEnum = EmailState.Error;
+ emailLog.ErrorMessage = errorMessage ?? "邮件发送失败,具体原因未知";
+ //await _emailLogRepository.UpdateAsync(emailLog);
+ break; // 找到匹配的就停止
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// 判断失败通知邮件是否与指定的EmailLog相关
+ ///
+ ///
+ ///
+ ///
+ private bool IsLikelyRelatedEmail(MimeMessage failureMessage, EmailLog emailLog)
+ {
+ var failureContent = failureMessage.HtmlBody ?? failureMessage.TextBody ?? failureMessage.Subject ?? string.Empty;
+ var emailSubject = emailLog.EmailSubject ?? string.Empty;
+
+ // 检查主题是否包含在失败通知中
+ if (!string.IsNullOrEmpty(emailSubject) &&
+ failureContent.Contains(emailSubject, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+
+ // 检查发件人是否匹配
+ if (!string.IsNullOrEmpty(emailLog.SenderAddress) &&
+ (failureContent.Contains(emailLog.SenderAddress, StringComparison.OrdinalIgnoreCase) ||
+ failureMessage.From.ToString().Contains(emailLog.SenderAddress, StringComparison.OrdinalIgnoreCase)))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
//private string AcquireOAuth2TokenByPassword()
//{
// if (_systemEmailConfig.OAuthTenantId.IsNullOrEmpty() || _systemEmailConfig.OAuthClientId.IsNullOrEmpty())
diff --git a/IRaCIS.Core.Domain/Common/EmailLog.cs b/IRaCIS.Core.Domain/Common/EmailLog.cs
index 4bdb3b4f5..460f1691f 100644
--- a/IRaCIS.Core.Domain/Common/EmailLog.cs
+++ b/IRaCIS.Core.Domain/Common/EmailLog.cs
@@ -58,6 +58,9 @@ public class EmailLog : BaseFullAuditEntity
///
public EmailState EmailStateEnum { get; set; }
+ [StringLength(5000)]
+ public string ErrorMessage { get; set; }
+
///
/// 邮件内容
///
diff --git a/IRaCIS.Core.Infra.EFCore/Migrations/20251128033532_EmailErrorMessage.Designer.cs b/IRaCIS.Core.Infra.EFCore/Migrations/20251128033532_EmailErrorMessage.Designer.cs
new file mode 100644
index 000000000..35d63fe53
--- /dev/null
+++ b/IRaCIS.Core.Infra.EFCore/Migrations/20251128033532_EmailErrorMessage.Designer.cs
@@ -0,0 +1,21270 @@
+//
+using System;
+using IRaCIS.Core.Infra.EFCore;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace IRaCIS.Core.Infra.EFCore.Migrations
+{
+ [DbContext(typeof(IRaCISDBContext))]
+ [Migration("20251128033532_EmailErrorMessage")]
+ partial class EmailErrorMessage
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.19")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.Attachment", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)")
+ .HasComment("编码");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DoctorId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ExpiryDate")
+ .HasColumnType("datetime2")
+ .HasComment("过期时间");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("IsAuthorizedView")
+ .HasColumnType("bit");
+
+ b.Property("IsOfficial")
+ .HasColumnType("bit")
+ .HasComment("是否正式简历");
+
+ b.Property("Language")
+ .HasColumnType("int")
+ .HasComment("1 中文 2为英文");
+
+ b.Property("Path")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("TrialId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)")
+ .HasComment("文件类型名");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("DoctorId");
+
+ b.ToTable("Attachment", t =>
+ {
+ t.HasComment("医生 - 简历|证书 文档表");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditDocument", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditDocumentTypeEnum")
+ .HasColumnType("int");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("FileFormat")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("FilePath")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("FileSize")
+ .HasPrecision(18, 2)
+ .HasColumnType("decimal(18,2)");
+
+ b.Property("IsAuthorization")
+ .HasColumnType("bit");
+
+ b.Property("MainFileId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ParentId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Version")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("MainFileId");
+
+ b.ToTable("AuditDocument", t =>
+ {
+ t.HasComment("稽查文档管理");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditDocumentClosure", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AncestorId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("祖先");
+
+ b.Property("Depth")
+ .HasColumnType("int");
+
+ b.Property("DescendantId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("后代");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AncestorId");
+
+ b.HasIndex("DescendantId");
+
+ b.ToTable("AuditDocumentClosure");
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditRecord", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditContent")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("AuditState")
+ .HasColumnType("int")
+ .HasComment("稽查状态");
+
+ b.Property("AuditTime")
+ .HasColumnType("date")
+ .HasComment("稽查日期");
+
+ b.Property("AuditType")
+ .HasColumnType("int")
+ .HasComment("稽查形式");
+
+ b.Property("BeginTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CompanyName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("EndTime")
+ .HasColumnType("datetime2");
+
+ b.Property("IsViewTrainingRecord")
+ .HasColumnType("bit");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("AuditRecord");
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditRecordIdentityUser", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditRecordId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("IdentityUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuditRecordId");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("IdentityUserId");
+
+ b.ToTable("AuditRecordIdentityUser");
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditRecordPermission", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditDocumentId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditRecordId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuditDocumentId");
+
+ b.HasIndex("AuditRecordId");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("AuditRecordPermission");
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.CRO", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CROCode")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("CROName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("CRONameCN")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("IsTrialLevel")
+ .HasColumnType("bit")
+ .HasComment("是否是项目级别");
+
+ b.Property("TrialId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("CROCompany", t =>
+ {
+ t.HasComment("机构 - CRO");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.CheckChallengeDialog", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("IsCRCNeedReply")
+ .HasColumnType("bit")
+ .HasComment("CRC是否需要回复 前端使用");
+
+ b.Property("ParamInfo")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasComment("核查的检查信息Json");
+
+ b.Property("SubjectVisitId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TalkContent")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("UserTypeEnum")
+ .HasColumnType("int")
+ .HasComment("核查过程中的操作用户类型");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("SubjectVisitId");
+
+ b.ToTable("CheckChallengeDialog", t =>
+ {
+ t.HasComment("一致性核查 - 对话记录表");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalAnswerRowInfo", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClinicalFormId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("表单Id");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("QuestionId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("问题Id");
+
+ b.Property("RowIndex")
+ .HasColumnType("int");
+
+ b.Property("SubjectId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("受试者Id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("ClinicalAnswerRowInfo", t =>
+ {
+ t.HasComment("受试者 - 临床表单表格问题行记录");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalDataSystemSet", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClinicalDataLevel")
+ .HasColumnType("int");
+
+ b.Property("ClinicalDataSetEnName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ClinicalDataSetEnum")
+ .HasColumnType("int")
+ .HasComment("枚举(字典里面取的)");
+
+ b.Property("ClinicalDataSetName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ClinicalUploadType")
+ .HasColumnType("int")
+ .HasComment("上传方式");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CriterionEnumListStr")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("EnFileName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("EnPath")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("IsApply")
+ .HasColumnType("bit")
+ .HasComment("是否应用");
+
+ b.Property("IsEnable")
+ .HasColumnType("bit");
+
+ b.Property("Path")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("UploadRole")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("ClinicalDataSystemSet", t =>
+ {
+ t.HasComment("系统 - 临床数据配置");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalDataTrialSet", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClinicalDataLevel")
+ .HasColumnType("int")
+ .HasComment("临床级别");
+
+ b.Property("ClinicalDataSetEnName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ClinicalDataSetName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ClinicalUploadType")
+ .HasColumnType("int")
+ .HasComment("上传方式");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CriterionEnumListStr")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("EnFileName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("EnPath")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("IsApply")
+ .HasColumnType("bit")
+ .HasComment("是否应用");
+
+ b.Property("IsConfirm")
+ .HasColumnType("bit");
+
+ b.Property("Path")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("SystemClinicalDataSetId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TrialId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UploadRole")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("SystemClinicalDataSetId");
+
+ b.HasIndex("TrialId");
+
+ b.ToTable("ClinicalDataTrialSet", t =>
+ {
+ t.HasComment("项目 - 临床数据适应标准配置");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalForm", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CheckDate")
+ .HasColumnType("datetime2")
+ .HasComment("检查日期");
+
+ b.Property("ClinicalDataTrialSetId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("PicturePath")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)")
+ .HasComment("截图地址");
+
+ b.Property("ReadingId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("SubjectId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("受试者Id");
+
+ b.Property("TrialId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("VisitId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClinicalDataTrialSetId");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("ReadingId");
+
+ b.HasIndex("SubjectId");
+
+ b.ToTable("ClinicalForm", t =>
+ {
+ t.HasComment("受试者 - 临床表单");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalQuestionAnswer", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Answer")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("ClinicalDataTrialSetId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClinicalFormId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("表单Id");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("QuestionId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("问题Id");
+
+ b.Property("SubjectId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("受试者Id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClinicalFormId");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("ClinicalQuestionAnswer", t =>
+ {
+ t.HasComment("受试者 - 临床表单问题答案");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalTableAnswer", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Answer")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)")
+ .HasComment("答案");
+
+ b.Property("ClinicalFormId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("表单Id");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("QuestionId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("问题Id");
+
+ b.Property("RowId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("答案行的Id");
+
+ b.Property("SubjectId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("受试者Id");
+
+ b.Property("TableQuestionId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("RowId");
+
+ b.ToTable("ClinicalTableAnswer", t =>
+ {
+ t.HasComment("受试者 - 临床表单表格问题答案");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.CommonDocument", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("BusinessScenarioEnum")
+ .HasColumnType("int")
+ .HasComment("业务场景");
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CriterionTypeEnum")
+ .HasColumnType("int")
+ .HasComment("系统标准枚举");
+
+ b.Property("DeleteUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeletedTime")
+ .HasColumnType("datetime2");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("FileTypeEnum")
+ .HasColumnType("int")
+ .HasComment("类型-上传|导出|邮件附件");
+
+ b.Property("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("NameCN")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("Path")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("CommonDocument", t =>
+ {
+ t.HasComment("数据上传 | 数据导出 | 邮件附件 文件记录表 (需要同步)");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.CriterionKeyFileRead", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("IdentityUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TrialCriterionId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("CriterionKeyFileRead", t =>
+ {
+ t.HasComment("标准阅读关键点");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.CriterionNidusSystem", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CriterionId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("IsSystemCriterion")
+ .HasColumnType("bit");
+
+ b.Property("LesionType")
+ .HasColumnType("int")
+ .HasComment("病灶类型");
+
+ b.Property("OrganType")
+ .HasColumnType("int")
+ .HasComment("器官类型");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("CriterionId");
+
+ b.ToTable("CriterionNidusSystem", t =>
+ {
+ t.HasComment("系统标准 - 病灶器官表 (需要同步)");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.CriterionNidusTrial", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CriterionId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("LesionType")
+ .HasColumnType("int");
+
+ b.Property("OrganType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("CriterionNidusTrial", t =>
+ {
+ t.HasComment("项目标准 - 病灶器官表");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.DataInspection", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("BatchId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("批次Id");
+
+ b.Property("ChildrenTypeId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("子类");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateUserName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)")
+ .HasComment("创建人姓名");
+
+ b.Property("CreateUserRealName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("DoctorUserId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("阅片医生");
+
+ b.Property("EntityName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)")
+ .HasComment("被稽查实体名");
+
+ b.Property("GeneralId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("要稽查对象Id");
+
+ b.Property("IP")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("Identification")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)")
+ .HasComment("标识");
+
+ b.Property("IsFrontAdd")
+ .HasColumnType("bit")
+ .HasComment("是否是前端添加");
+
+ b.Property("IsSign")
+ .HasColumnType("bit");
+
+ b.Property("JsonDetail")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("LastJsonDetail")
+ .HasColumnType("nvarchar(max)")
+ .HasComment("上一条json");
+
+ b.Property("ModuleTypeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ObjectRelationParentId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("被稽查对象外键1");
+
+ b.Property("ObjectRelationParentId2")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ObjectRelationParentId3")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ObjectTypeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("OptTypeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ParentId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("父ID");
+
+ b.Property("Reason")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("RoleName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)")
+ .HasComment("角色名称");
+
+ b.Property("SignId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("SubjectId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("SubjectVisitId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TrialId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TrialReadingCriterionId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TrialSiteId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("VisitStageId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("访视计划ID");
+
+ b.Property("VisitTaskId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("TrialReadingCriterionId");
+
+ b.HasIndex("VisitTaskId");
+
+ b.ToTable("DataInspection", t =>
+ {
+ t.HasComment("稽查 - 记录表");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.DicomInstance", b =>
+ {
+ b.Property("SeqId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Anonymize")
+ .HasColumnType("bit");
+
+ b.Property("BitsAllocated")
+ .HasColumnType("int");
+
+ b.Property("CPIStatus")
+ .HasColumnType("bit");
+
+ b.Property("CorrectedImage")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DecayCorrection")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("DeleteUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeletedTime")
+ .HasColumnType("datetime2");
+
+ b.Property("EncapsulatedDocument")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("FileSize")
+ .HasColumnType("bigint");
+
+ b.Property("FrameOfReferenceUID")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("FrameTime")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("HtmlPath")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ImageColumns")
+ .HasColumnType("int");
+
+ b.Property("ImageOrientationPatient")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ImagePositionPatient")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ImageRows")
+ .HasColumnType("int");
+
+ b.Property("ImagerPixelSpacing")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("InstanceNumber")
+ .HasColumnType("int");
+
+ b.Property("InstanceTime")
+ .HasColumnType("datetime2");
+
+ b.Property("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property("IsEncapsulated")
+ .HasColumnType("bit");
+
+ b.Property("IsReading")
+ .HasColumnType("bit");
+
+ b.Property("MediaStorageSOPClassUID")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("MediaStorageSOPInstanceUID")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("NumberOfFrames")
+ .HasColumnType("int");
+
+ b.Property("Path")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("PhotometricInterpretation")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("PixelRepresentation")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("PixelSpacing")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("RescaleIntercept")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("RescaleSlope")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("SOPClassUID")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("SequenceOfUltrasoundRegions")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("SeriesId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("SeriesInstanceUid")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("SliceLocation")
+ .HasColumnType("int");
+
+ b.Property("SliceThickness")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("SopInstanceUid")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("StudyId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("StudyInstanceUid")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("SubjectId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property