using IRaCIS.Core.Domain.BaseModel; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Infra.EFCore.Common; using IRaCIS.Core.Infrastructure.Encryption; using IRaCIS.Core.Infrastructure.Extention; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Newtonsoft.Json; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Data; using System.Reflection; using System.Security.Cryptography; using System.Text; namespace IRaCIS.Core.Infra.EFCore; #region 连接池废弃 /// /// 报错,添加subject 报错,重复添加访视 /// //public class IRaCISDBScopedFactory : IDbContextFactory //{ // private readonly IDbContextFactory _pooledFactory; // private readonly IUserInfo _userInfo; // public IRaCISDBScopedFactory(IDbContextFactory pooledFactory,IUserInfo userInfo) // { // _pooledFactory = pooledFactory; // _userInfo = userInfo; // } // public IRaCISDBContext CreateDbContext() // { // var context = _pooledFactory.CreateDbContext(); // context._userInfo = _userInfo; // return context; // } //} #endregion public class IRaCISDBContext : DbContext { public IRaCISDBContext(DbContextOptions options) : base(options) { } /// /// efcore codefirst 防止数据注解过多配置,全局统一配置 /// /// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { //decimal 不配置,默认精度是18,2 //configurationBuilder.Conventions.Add(_ => new DecimalPrecisionConvention(18,2)); //针对字符串使用默认的长度配置为200,如果标注了StringLength 其他长度,就是标注的长度,如果标注了MaxLength 那么就是nvarcharMax configurationBuilder.Conventions.Add(_ => new DefaultStringLengthConvention(400)); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity(entity => { // 使用部分加密值转换器,前 2 个字符不加密,方便模糊搜索 entity.Property(e => e.Name).HasConversion(new PartialEncryptionConverter(2)); //entity.OwnsMany(x => x.TestJsonObjectLsit, ownedNavigationBuilder => //{ // ownedNavigationBuilder.ToJson(); //}); entity.Property(e => e.TestJsonObjectLsit).HasConversion(v => v == null ? "[]" : JsonConvert.SerializeObject(v), v => string.IsNullOrEmpty(v) ? null : JsonConvert.DeserializeObject>(v)); }); modelBuilder.Entity(entity => { //项目术语配置 entity.OwnsMany(x => x.TrialObjectNameList, ownedNavigationBuilder => { ownedNavigationBuilder.ToJson(); }); entity.OwnsMany(x => x.StudyNameList, ownedNavigationBuilder => { ownedNavigationBuilder.ToJson(); }); }); #region pgsql codefirst 配置 暂时屏蔽 //if (base.Database.IsNpgsql()) //{ // modelBuilder.HasPostgresExtension("uuid-ossp"); // //保证pgsql 生成的时间默认为timestamp 而不是 timestamp with time zone // foreach (var entityType in modelBuilder.Model.GetEntityTypes()) // { // foreach (var property in entityType.GetProperties()) // { // if (property.ClrType == typeof(DateTime) || property.ClrType == typeof(DateTime?)) // { // property.SetColumnType("timestamp without time zone"); // } // } // } //} #endregion #region decimal 自定义精度,适配多种数据库 foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { foreach (var property in entityType.GetProperties()) { // 如果属性类型是 decimal 或 nullable decimal if (property.ClrType == typeof(decimal) || property.ClrType == typeof(decimal?)) { // 获取自定义的 DecimalPrecisionAttribute var precisionAttr = property.PropertyInfo?.GetCustomAttributes(typeof(DecimalPrecisionAttribute), false) .FirstOrDefault() as DecimalPrecisionAttribute; if (precisionAttr != null) { property.SetPrecision(precisionAttr.Precision); property.SetScale(precisionAttr.Scale); } else { // 默认的精度设置 property.SetPrecision(18); property.SetScale(2); } } } } #endregion //遍历实体模型手动配置 var typesToRegister = Assembly.GetExecutingAssembly().GetTypes().Where(q => q.GetInterface(typeof(IEntityTypeConfiguration<>).FullName) != null); foreach (var type in typesToRegister) { dynamic configurationInstance = Activator.CreateInstance(type); modelBuilder.ApplyConfiguration(configurationInstance); } base.OnModelCreating(modelBuilder); //软删除筛选器通常依赖于实体模型的完整定义(例如属性映射、继承关系等) foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { // 软删除配置 if (typeof(ISoftDelete).IsAssignableFrom(entityType.ClrType)) { //entityType.AddSoftDeleteQueryFilter(); // 动态创建表达式:e => e.IsDeleted==false var parameter = Expression.Parameter(entityType.ClrType, "e"); var property = Expression.Property(parameter, nameof(ISoftDelete.IsDeleted)); var filter = Expression.Lambda( Expression.Equal(property, Expression.Constant(false)), parameter); // 应用全局查询筛选器 modelBuilder.Entity(entityType.ClrType).HasQueryFilter(filter); //Console.WriteLine($"实体应用软删除:{entityType.ClrType.Name}"); } foreach (var navigation in entityType.GetNavigations()) { if (navigation.IsCollection) continue; #region 有问题 // 比如 e.SourceSubjectVisit.IsDeleted == False 还会导致 dicom 查询增加额外很多的连表 因为访视 项目 项目中心,dicom 都是软删除 // //// 配置基于导航属性的软删除查询筛选器 //if (typeof(ISoftDelete).IsAssignableFrom(navigation.TargetEntityType.ClrType)) //{ // var clrType = entityType.ClrType; // var targetType = navigation.TargetEntityType.ClrType; // //e => e.Subject.IsDeleted==false // var parameterNav = Expression.Parameter(clrType, "e"); // var navigationProperty = Expression.Property(parameterNav, navigation.Name); // var navigationFilter = Expression.Equal( // Expression.Property(navigationProperty, nameof(ISoftDelete.IsDeleted)), // Expression.Constant(false)); // var filterNav = Expression.Lambda(navigationFilter, parameterNav); // modelBuilder.Entity(clrType).HasQueryFilter(filterNav); // Console.WriteLine($"实体应用软删除:{entityType.ClrType.Name} 导航属性{filterNav}"); //} #endregion } if (typeof(Entity).IsAssignableFrom(entityType.ClrType)) { modelBuilder.Entity(entityType.ClrType).Property(nameof(Entity.Id)).HasValueGenerator(); } if (typeof(IEntitySeqId).IsAssignableFrom(entityType.ClrType)) { modelBuilder.Entity(entityType.ClrType).Property(nameof(IEntitySeqId.SeqId)).HasValueGenerator(); } } } #region 获取表名 和字段名 优化 /// /// 直接获取代码定义的模型,以及表上定义的Description 获取表信息 以及备注 /// /// public List GetContextTablesList() { var tableList = new List(); foreach (var entityType in this.Model.GetEntityTypes()) { var clrType = entityType.ClrType; var tableName = entityType.GetTableName(); var tableDescription = clrType.GetCustomAttribute()?.Description ?? string.Empty; tableList.Add(new TableList { Name = tableName, Remake = tableDescription, }); } return tableList; } /// /// 直接获取代码定义的某个表的属性,以及属性上定义的Description 获取备注 /// /// public List GetContextTableColumnList(string tableName) { var tableColumList = new List(); var entityType = this.Model.GetEntityTypes().FirstOrDefault(t => t.GetTableName().ToLower() == tableName.ToLower()); if (entityType == null) { throw new ArgumentException($"Table '{tableName}' not found."); } var clrType = entityType.ClrType; foreach (var property in entityType.GetProperties()) { var columnName = property.GetColumnName(); var columnDescription = clrType.GetProperty(property.Name)?.GetCustomAttribute()?.Description ?? string.Empty; tableColumList.Add(new TableList { Name = columnName, Remake = columnDescription, }); } return tableColumList.OrderBy(t => t.Name).ToList(); } #endregion #region Doctor public virtual DbSet Dictionary { get; set; } public virtual DbSet Doctor { get; set; } public virtual DbSet DoctorSummarize { get; set; } public virtual DbSet DoctorCriterionFile { get; set; } public virtual DbSet DoctorDictionary { get; set; } public virtual DbSet Postgraduate { get; set; } public virtual DbSet Education { get; set; } public virtual DbSet ResearchPublications { get; set; } public virtual DbSet TrialExperience { get; set; } public virtual DbSet Vacation { get; set; } public virtual DbSet Attachment { get; set; } public virtual DbSet TrialExperienceCriteria { get; set; } #endregion #region Enroll public virtual DbSet DoctorWorkload { get; set; } public virtual DbSet Enroll { get; set; } public virtual DbSet EnrollReadingCategory { get; set; } public virtual DbSet EnrollDetails { get; set; } #endregion #region Reading public virtual DbSet TrialCriterionDictionaryCode { get; set; } public virtual DbSet ReadingCustomTag { get; set; } public virtual DbSet SystemCriterionDictionaryCode { get; set; } public virtual DbSet ReadingTaskRelation { get; set; } public virtual DbSet OrganInfo { get; set; } public virtual DbSet ReadingSystemCriterionDictionary { get; set; } public virtual DbSet ReadingTableAnswerRowInfo { get; set; } public virtual DbSet OrganTrialInfo { get; set; } public virtual DbSet ReadingTableQuestionSystem { get; set; } public virtual DbSet ReadingPeriodSet { get; set; } public virtual DbSet ReadingTaskQuestionAnswer { get; set; } public virtual DbSet ReadingPeriodPlan { get; set; } public virtual DbSet ReadingClinicalData { get; set; } public virtual DbSet ReadingOncologyTaskInfo { get; set; } public virtual DbSet ReadingGlobalTaskInfo { get; set; } public virtual DbSet ReadingQuestionCriterionSystem { get; set; } public virtual DbSet ReadingQuestionCriterionTrial { get; set; } public virtual DbSet ReadingQuestionSystem { get; set; } public virtual DbSet ReadingQuestionTrial { get; set; } public virtual DbSet ReadingClinicalDataPDF { get; set; } public virtual DbSet ReadingConsistentClinicalData { get; set; } public virtual DbSet ReadingConsistentClinicalDataPDF { get; set; } public virtual DbSet ReadingJudgeInfo { get; set; } public virtual DbSet ReadingNoneDicomMark { get; set; } public virtual DbSet ReadModule { get; set; } public virtual DbSet ClinicalDataTrialSet { get; set; } public virtual DbSet ClinicalDataSystemSet { get; set; } public virtual DbSet ReadingMedicineSystemQuestion { get; set; } public virtual DbSet ReadingMedicineTrialQuestion { get; set; } public virtual DbSet ReadingMedicineQuestionAnswer { get; set; } public virtual DbSet ReadingMedicalReviewDialog { get; set; } public virtual DbSet CriterionNidusSystem { get; set; } public virtual DbSet CriterionNidusTrial { get; set; } public virtual DbSet ReadingTrialCriterionDictionary { get; set; } public virtual DbSet ReadingTableQuestionTrial { get; set; } public virtual DbSet TumorAssessment_RECIST1Point1BM { get; set; } public virtual DbSet TumorAssessment_RECIST1Point1 { get; set; } public virtual DbSet TumorAssessment_IRECIST1Point1 { get; set; } public virtual DbSet TrialClinicalDataSetCriterion { get; set; } public virtual DbSet TrialCriterionAdditionalAssessmentType { get; set; } public virtual DbSet SubjectCriteriaEvaluation { get; set; } public virtual DbSet SubjectAdditionalEvaluationResult { get; set; } public virtual DbSet SubjectCriteriaEvaluationVisitFilter { get; set; } public virtual DbSet SubjectCriteriaEvaluationVisitStudyFilter { get; set; } public virtual DbSet ReadingTaskQuestionMark { get; set; } //public virtual DbSet TrialClinicalDataCriterion { get; set; } //public virtual DbSet SystemClinicalDataCriterion { get; set; } #endregion #region Subject and Visit and study public virtual DbSet StudyMonitor { get; set; } public virtual DbSet Subject { get; set; } public virtual DbSet VisitPlans { get; set; } public virtual DbSet VisitPlanInfluenceStudy { get; set; } public virtual DbSet VisitPlanInfluenceStat { get; set; } public virtual DbSet NoneDicomStudyFile { get; set; } public virtual DbSet NoneDicomStudy { get; set; } public virtual DbSet PreviousPDF { get; set; } public virtual DbSet PreviousSurgery { get; set; } public virtual DbSet PreviousOther { get; set; } public virtual DbSet PreviousHistory { get; set; } public virtual DbSet DicomStudys { get; set; } public virtual DbSet DicomSeries { get; set; } public virtual DbSet DicomInstances { get; set; } public virtual DbSet ImageShare { get; set; } #endregion #region Management public virtual DbSet VerificationCodes { get; set; } public virtual DbSet MenuFunctions { get; set; } public virtual DbSet UserTypeMenuFunction { get; set; } public virtual DbSet Users { get; set; } public virtual DbSet UserType { get; set; } #endregion #region Institution public virtual DbSet Hospitals { get; set; } public virtual DbSet CROCompany { get; set; } public virtual DbSet Sponsor { get; set; } #endregion #region Trial public virtual DbSet Trial { get; set; } public virtual DbSet TrialDictionary { get; set; } public virtual DbSet TrialDetail { get; set; } public virtual DbSet UserTrial { get; set; } public virtual DbSet ProjectDictionary { get; set; } public virtual DbSet UserTrialSite { get; set; } public virtual DbSet TrialSite { get; set; } public virtual DbSet Site { get; set; } public virtual DbSet User { get; set; } public virtual DbSet UserPassWordLog { get; set; } public virtual DbSet TrialSiteUserSurvey { get; set; } public virtual DbSet TrialSiteEquipmentSurvey { get; set; } public virtual DbSet TrialSiteSurvey { get; set; } #endregion #region Financial public virtual DbSet ReviewerPayInformation { get; set; } public virtual DbSet RankPrice { get; set; } public virtual DbSet TrialPaymentPrice { get; set; } public virtual DbSet AwardPrice { get; set; } public virtual DbSet Payment { get; set; } public virtual DbSet PaymentDetail { get; set; } public virtual DbSet ExchangeRate { get; set; } public virtual DbSet TrialRevenuesPrice { get; set; } public virtual DbSet PaymentAdjustment { get; set; } public virtual DbSet TrialRevenuesPriceVerification { get; set; } #endregion #region QC public virtual DbSet TrialQCQuestionConfigure { get; set; } public virtual DbSet QCQuestionConfigure { get; set; } public virtual DbSet TrialQCQuestionAnswer { get; set; } public virtual DbSet CheckChallengeDialog { get; set; } #endregion #region QA public virtual DbSet QCChallengeDialog { get; set; } //public virtual DbSet QATemplateDictionary { get; set; } public virtual DbSet QCChallenge { get; set; } public virtual DbSet SubjectVisit { get; set; } #endregion #region ClinicalQuestion public virtual DbSet TrialClinicalQuestion { get; set; } public virtual DbSet SystemClinicalQuestion { get; set; } public virtual DbSet SystemClinicalTableQuestion { get; set; } public virtual DbSet TrialClinicalTableQuestion { get; set; } public virtual DbSet ClinicalQuestionAnswer { get; set; } public virtual DbSet ClinicalAnswerRowInfo { get; set; } public virtual DbSet ClinicalTableAnswer { get; set; } public virtual DbSet ReadModuleCriterionFrom { get; set; } public virtual DbSet ClinicalForm { get; set; } #endregion #region Document public virtual DbSet SystemDocument { get; set; } public virtual DbSet SystemDocumentAttachment { get; set; } public virtual DbSet TrialDocument { get; set; } public virtual DbSet TrialDocumentAttachment { get; set; } public virtual DbSet TrialDocUserTypeConfirm { get; set; } public virtual DbSet SystemDocNeedConfirmedUserType { get; set; } public virtual DbSet TrialDocNeedConfirmedUserType { get; set; } #endregion #region 未分类 public virtual DbSet ShortcutKey { get; set; } public virtual DbSet UserWLTemplate { get; set; } public virtual DbSet EmailNoticeConfig { get; set; } public virtual DbSet SystemBasicData { get; set; } public virtual DbSet TrialSign { get; set; } public virtual DbSet TrialStateChange { get; set; } public virtual DbSet SystemAnonymization { get; set; } public virtual DbSet TrialExternalUser { get; set; } public virtual DbSet UserTypeGroup { get; set; } public virtual DbSet DataInspection { get; set; } public virtual DbSet FrontAuditConfig { get; set; } public virtual DbSet TrialAuditShow { get; set; } public virtual DbSet InspectionFile { get; set; } public virtual DbSet CommonDocument { get; set; } public virtual DbSet SystemNotice { get; set; } public virtual DbSet SystemNoticeUserRead { get; set; } public virtual DbSet SystemNoticeUserType { get; set; } public virtual DbSet ReadingTableQuestionAnswer { get; set; } public virtual DbSet PublishLog { get; set; } public virtual DbSet UserLog { get; set; } public virtual DbSet EmailNoticeUserType { get; set; } public virtual DbSet TrialEmailBlackUser { get; set; } public virtual DbSet TrialBodyPart { get; set; } public virtual DbSet ExploreRecommend { get; set; } public virtual DbSet SCPPatient { get; set; } public virtual DbSet SCPStudy { get; set; } public virtual DbSet SCPSeries { get; set; } public virtual DbSet SCPInstance { get; set; } public virtual DbSet TrialDicomAE { get; set; } public virtual DbSet TrialSiteDicomAE { get; set; } public virtual DbSet SCPImageUpload { get; set; } public virtual DbSet UserFeedBack { get; set; } public virtual DbSet TaskAllocationRule { get; set; } public virtual DbSet VisitTask { get; set; } public virtual DbSet SubjectUser { get; set; } public virtual DbSet VisitTaskReReading { get; set; } public virtual DbSet TaskMedicalReview { get; set; } public virtual DbSet TaskMedicalReviewRule { get; set; } public virtual DbSet TaskConsistentRule { get; set; } public virtual DbSet TaskInfluence { get; set; } public virtual DbSet SubjectCanceDoctor { get; set; } public virtual DbSet TrialEmailNoticeConfig { get; set; } public virtual DbSet TrialEmailNoticeUser { get; set; } public virtual DbSet Internationalization { get; set; } public virtual DbSet TrialVirtualSiteCodeUpdate { get; set; } public virtual DbSet EnrollReadingCriterion { get; set; } #endregion public virtual DbSet TrialImageDownload { get; set; } public virtual DbSet TestLength { get; set; } public virtual DbSet EventStoreRecord { get; set; } public virtual DbSet IdentityUser { get; set; } public virtual DbSet TrialIdentityUser { get; set; } public virtual DbSet SystemDocConfirmedIdentityUser { get; set; } public virtual DbSet TrialDocConfirmedIdentityUser { get; set; } #region 报告、 文档、记录 public virtual DbSet AuditDocument { get; set; } public virtual DbSet SysFileType { get; set; } public virtual DbSet TrialFileType { get; set; } public virtual DbSet TrialFinalRecord { get; set; } public virtual DbSet TrialNormalRecord { get; set; } public virtual DbSet TrialTrianingRecord { get; set; } public virtual DbSet TrialFile { get; set; } public virtual DbSet TrialHistoryRecordFile { get; set; } #endregion public virtual DbSet SubjectVisitImageBackRecord { get; set; } } public class TestLength : Entity { public string Name { get; set; } [StringLength(1000)] public string[] StringList { get; set; } = new string[] { }; public List DateTimeList { get; set; } = new List(); [StringLength(1000)] public List TestEnumList { get; set; } = new List(); public List TestJsonObjectLsit { get; set; } public DateOnly? TestDate { get; set; } } public record TestJsonObject { public string Name { get; set; } public string Description { get; set; } } public enum TestEnum { Default = 0, First = 1 }