using IRaCIS.Core.Domain.Models; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.ChangeTracking; using System.Reflection; using EntityFramework.Exceptions.SqlServer; using IRaCIS.Core.Domain.Share; using MassTransit; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.ValueGeneration; using UserTypeGroup = IRaCIS.Core.Domain.Models.UserTypeGroup; using IRaCIS.Core.Infra.EFCore.Common; using IRaCIS.Core.Infra.EFCore.Common.Dto; using Microsoft.Identity.Client; using EntityFramework.Exceptions.Common; using System.Data; using IRaCIS.Core.Infrastructure; using System.Reflection.Metadata; namespace IRaCIS.Core.Infra.EFCore { /// /// 报错,添加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; // } //} public class IRaCISDBContext : DbContext { private IUserInfo _userInfo; private readonly ILogger _logger; public IRaCISDBContext(DbContextOptions options, IUserInfo userInfo, ILogger logger ) : base(options) { _userInfo = userInfo; _logger = logger; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity(builder => { builder.HasBaseType((Type)null); builder.ToView(null); builder.HasNoKey(); }); modelBuilder.Entity().HasQueryFilter(p => p.IsAdditional == false); modelBuilder.Entity().HasMany(t => t.VisitTaskList).WithOne(t => t.DoctorUser).HasForeignKey(t => t.DoctorUserId).IsRequired(false); //modelBuilder.Entity().HasMany(t => t.DoctorTrialVisitTaskList).WithOne(t => t.DoctorTaskMedicalReviewRule).HasForeignKey(t => new { t.DoctorUserId, t.TrialId }).HasPrincipalKey(u => new { u.DoctorUserId, u.TrialId }); //modelBuilder.Entity().HasMany(t => t.TaskMedicalReviewList).WithOne(t => t.TaskMedicalReviewRule).HasForeignKey(t => new { t.DoctorUserId, t.TrialId }).HasPrincipalKey(u => new { u.DoctorUserId, u.TrialId }); //会导致级联删除 //modelBuilder.Entity().HasMany(t => t.SubjectArmVisitTaskList).WithOne(t => t.SujectArm).HasForeignKey(t => new { t.SubjectId, t.ArmEnum }).HasPrincipalKey(u => new { u.SubjectId, u.ArmEnum }) // ./*IsRequired(false)*/OnDelete(DeleteBehavior.NoAction); // modelBuilder.Entity().HasOne(t => t.SujectArm).WithMany(s => s.SubjectArmVisitTaskList).HasForeignKey(t => new { t.SubjectId, t.ArmEnum }).HasPrincipalKey(u => new { u.SubjectId, u.ArmEnum }); modelBuilder.Entity().HasMany(t => t.JudgeVisitList).WithOne(t => t.JudgeVisitTask); modelBuilder.Entity().HasMany(t => t.TaskMedicalReviewList).WithOne(t => t.VisitTask).HasForeignKey(t => t.VisitTaskId); modelBuilder.Entity().HasOne(t => t.Subject).WithMany(s => s.SubjectVisitTaskList).HasForeignKey(t => t.SubjectId); modelBuilder.Entity().HasMany(t => t.TaskInfluenceList).WithOne(s => s.OriginalTask).HasForeignKey(t => t.OriginalTaskId); modelBuilder.Entity().HasMany(t => t.GlobalVisitResultList).WithOne(s => s.GlobalVisitTask).HasForeignKey(t => t.GlobalTaskId); modelBuilder.Entity().HasMany(t => t.ChildList).WithOne(t => t.Parent); modelBuilder.Entity().HasMany(t => t.EarlierSubjectUserList).WithOne(t => t.OrignalSubjectUser); modelBuilder.Entity().HasQueryFilter(b => b.Subject.IsDeleted == false); //遍历实体模型手动配置 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(); } if (typeof(Entity).IsAssignableFrom(entityType.ClrType)) { modelBuilder.Entity(entityType.ClrType).Property(nameof(Entity.Id)).HasValueGenerator(); } } } #region public IQueryable GetTableList() { return Set().FromSqlRaw("EXEC dbo.procGetTableList"); } public IQueryable GetTableColumn(string tableName) { return Set().FromSqlRaw($"EXEC dbo.procGetTableColumn {tableName}"); } #endregion #region Doctor public virtual DbSet Dictionary { get; set; } public virtual DbSet Doctor { 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 UserDoctor { 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 ReadingClinicalDataView { 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 ReadModule { get; set; } public virtual DbSet ReadModuleView { 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 Roles { get; set; } public virtual DbSet UserTypeMenuFunction { get; set; } public virtual DbSet Users { get; set; } public virtual DbSet TrialAudit { get; set; } public virtual DbSet UserType { get; set; } public virtual DbSet SaveChangesAudits { 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 TrialDocument { get; set; } public virtual DbSet TrialDocUserTypeConfirm { get; set; } public virtual DbSet SystemDocConfirmedUser { get; set; } public virtual DbSet SystemDocNeedConfirmedUserType { get; set; } public virtual DbSet TrialDocNeedConfirmedUserType { get; set; } public virtual DbSet TrialDocConfirmedUser { get; set; } #endregion #region 暂时未用 #region 工作量分配 //public virtual DbSet WorkloadTPs { get; set; } //public virtual DbSet WorkloadGlobals { get; set; } //public virtual DbSet WorkloadADs { get; set; } //public virtual DbSet WorkloadDetails { get; set; } #endregion //public virtual DbSet SysMessages { get; set; } //public virtual DbSet TrialAttachment { get; set; } //public virtual DbSet SystemLogs { get; set; } //public virtual DbSet TU { get; set; } //public virtual DbSet TR { get; set; } //public virtual DbSet RS { get; set; } //public virtual DbSet Reports { get; set; } //public virtual DbSet StudyReviewer { get; set; } //public virtual DbSet KeyInstances { get; set; } //public virtual DbSet GlobalRS { get; set; } //public virtual DbSet GlobalResult { get; set; } //public virtual DbSet ImageLabels { get; set; } //public virtual DbSet QaTemplateItem { get; set; } //public virtual DbSet QaTemplateItemDictionary { get; set; } //public virtual DbSet QaTemplateTemplateItem { get; set; } //public virtual DbSet QATrailTemplate { get; set; } //public virtual DbSet QATrialTemplateItem { get; set; } //public virtual DbSet QARecordTrialTemplateItem { get; set; } //public virtual DbSet QARecordTemplateItemDetail { get; set; } //public virtual DbSet QATemplate { get; set; } //public virtual DbSet QANoticeUser { get; set; } //public virtual DbSet QANotice { get; set; } //public virtual DbSet TrialUserPreparation { get; set; } #endregion 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 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 override async Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) { // 采用触发器的方式 设置 CreateUserId CreateTime UpdateTime UpdateUserId 稽查实体里面没有这四个字段的值 因为先后顺序的原因 await AddAudit(); try { return await base.SaveChangesAsync(cancellationToken); } catch (UniqueConstraintException ex) { _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("该唯一键已经存在于数据库中。"); } catch (TimeoutException ex) { _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("数据库操作已经超时,请稍后重试。"); } catch (CannotInsertNullException ex) { _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("无法在非空列上插入空值。"); } catch (MaxLengthExceededException ex) { _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("字符串超过了数据库列的最大长度。"); } catch (NumericOverflowException ex) { _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("数值超过了数据类型的范围。"); } catch (SyntaxErrorException ex) { _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("SQL 查询中存在语法错误。"); } catch (ReferenceConstraintException ex) { _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("无法进行当前操作,当前数据不符合外键约束。"); } catch (DbUpdateConcurrencyException ex) { _logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message); throw new DBSaveFailedException("SQL 事务失败,请检查环境。"); } } public async Task AddAudit() { //触发器里面提交事务 业务方法里面提交事务 会记录两次 var inspectionGeneralIdList = ChangeTracker.Entries().Where(t => typeof(DataInspection).IsAssignableFrom(t.Entity.GetType())).Select(t => ((DataInspection)t.Entity).GeneralId).ToList(); var entities = ChangeTracker.Entries().Where(u => (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added)) .Where(t => !typeof(DataInspection).IsAssignableFrom(t.Entity.GetType()) && !inspectionGeneralIdList.Contains(((Entity)t.Entity).Id)) .ToList(); AuditingData auditingData = new AuditingData(this, _userInfo); //await auditingData.IncomingEntitys(entities); if (entities.Count > 0) { await auditingData.InsertAddEntitys(entities); } } 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; } } public class MySequentialGuidValueGenerator : ValueGenerator { public override Guid Next(EntityEntry entry) { return NewId.NextGuid(); } public override bool GeneratesTemporaryValues => false; } }