irc-netcore-api/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs

555 lines
21 KiB
C#

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 IRaCIS.Core.Infra.EFCore.ValueGenerator;
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;
namespace IRaCIS.Core.Infra.EFCore
{
public class IRaCISDBContext : DbContext
{
public readonly IUserInfo _userInfo;
//private readonly IAuditingData _auditingData;
// 在控制台
//public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });
// 调试窗口
public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddDebug(); });
public IRaCISDBContext(DbContextOptions<IRaCISDBContext> options, IUserInfo userInfo
//IAuditingData auditingData
) : base(options)
{
_userInfo = userInfo;
//this._auditingData = auditingData;
//_configuration = configuration;
}
//比数据库上下文构造函数先执行 不能构造函数注入的方式使用配置文件
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLoggerFactory(MyLoggerFactory)
.ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactoryDesignTimeSupport>();
optionsBuilder.UseExceptionProcessor();
//var config = new ConfigurationBuilder()
// .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true).Build();
//connectionString = config.GetSection("ConnectionStrings:RemoteNew").Value;
//optionsBuilder.AddInterceptors(new AuditingInterceptor(connectionString));
}
#region IModelCacheKeyFactory
public class DynamicModelCacheKeyFactoryDesignTimeSupport : IModelCacheKeyFactory
{
public object Create(DbContext context, bool designTime)
=> context is IRaCISDBContext dynamicContext
? (context.GetType(), dynamicContext._userInfo.IsEn_Us, designTime)
: (object)context.GetType();
public object Create(DbContext context)
=> Create(context, false);
}
#endregion
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TableList>(builder =>
{
builder.HasBaseType((Type)null);
builder.ToView(null);
builder.HasNoKey();
});
//modelBuilder.HasDbFunction(typeof(DbContext).GetMethod(nameof(GetTableList)));
modelBuilder.Entity<Dictionary>().HasMany(t => t.ChildList).WithOne(t => t.Parent);
if (_userInfo.IsEn_Us)
{
modelBuilder.Entity<Dictionary>().Property(t => t.MappedValue).HasColumnName(nameof(Domain.Models.Dictionary.Value));
}
else
{
modelBuilder.Entity<Dictionary>().Property(t => t.MappedValue).HasColumnName(nameof(Domain.Models.Dictionary.ValueCN));
}
//遍历实体模型手动配置
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<Guid>(nameof(Entity.Id)).HasValueGenerator<MySequentialGuidValueGenerator>();
}
}
}
#region
public IQueryable<TableList> GetTableList()
{
return Set<TableList>().FromSqlRaw("EXEC dbo.procGetTableList");
}
public IQueryable<TableList> GetTableColumn(string tableName)
{
return Set<TableList>().FromSqlRaw($"EXEC dbo.procGetTableColumn {tableName}");
}
#endregion
#region Doctor
public virtual DbSet<Dictionary> Dictionary { get; set; }
public virtual DbSet<Doctor> Doctor { get; set; }
public virtual DbSet<DoctorDictionary> DoctorDictionary { get; set; }
public virtual DbSet<Postgraduate> Postgraduate { get; set; }
public virtual DbSet<Education> Education { get; set; }
public virtual DbSet<ResearchPublication> ResearchPublications { get; set; }
public virtual DbSet<TrialExperience> TrialExperience { get; set; }
public virtual DbSet<UserDoctor> UserDoctor { get; set; }
public virtual DbSet<Vacation> Vacation { get; set; }
public virtual DbSet<Attachment> Attachment { get; set; }
public virtual DbSet<TrialExperienceCriteria> TrialExperienceCriteria { get; set; }
#endregion
#region Enroll
public virtual DbSet<Workload> DoctorWorkload { get; set; }
public virtual DbSet<Enroll> IntoGroup { get; set; }
public virtual DbSet<EnrollDetail> EnrollDetails { get; set; }
#endregion
#region Reading
public virtual DbSet<ReadingPeriodSet> ReadingPeriodSet { get; set; }
public virtual DbSet<ReadModule> ReadModule { get; set; }
#endregion
#region Subject and Visit and study
public virtual DbSet<StudyMonitor> StudyMonitor { get; set; }
public virtual DbSet<Subject> Subject { get; set; }
public virtual DbSet<VisitStage> VisitPlans { get; set; }
public virtual DbSet<VisitPlanInfluenceStudy> VisitPlanInfluenceStudy { get; set; }
public virtual DbSet<VisitPlanInfluenceStat> VisitPlanInfluenceStat { get; set; }
public virtual DbSet<NoneDicomStudyFile> NoneDicomStudyFile { get; set; }
public virtual DbSet<NoneDicomStudy> NoneDicomStudy { get; set; }
public virtual DbSet<PreviousPDF> PreviousPDF { get; set; }
public virtual DbSet<PreviousSurgery> PreviousSurgery { get; set; }
public virtual DbSet<PreviousOther> PreviousOther { get; set; }
public virtual DbSet<PreviousHistory> PreviousHistory { get; set; }
public virtual DbSet<StudyDTF> StudyDTF { get; set; }
public virtual DbSet<DicomStudy> DicomStudys { get; set; }
public virtual DbSet<DicomSeries> DicomSeries { get; set; }
public virtual DbSet<DicomInstance> DicomInstances { get; set; }
public virtual DbSet<ImageShare> ImageShare { get; set; }
#endregion
#region Management
public virtual DbSet<VerificationCode> VerificationCodes { get; set; }
public virtual DbSet<Menu> MenuFunctions { get; set; }
public virtual DbSet<Role> Roles { get; set; }
public virtual DbSet<UserTypeMenu> UserTypeMenuFunction { get; set; }
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<UserRole> UserRoles { get; set; }
public virtual DbSet<TrialAudit> TrialAudit { get; set; }
public virtual DbSet<UserType> UserType { get; set; }
public virtual DbSet<SaveChangesAudit> SaveChangesAudits { get; set; }
#endregion
#region Institution
public virtual DbSet<Site> ResearchCenter { get; set; }
public virtual DbSet<Hospital> Hospitals { get; set; }
public virtual DbSet<CRO> CROCompany { get; set; }
public virtual DbSet<Sponsor> Sponsor { get; set; }
#endregion
#region Trial
public virtual DbSet<Trial> Trial { get; set; }
public virtual DbSet<TrialDictionary> TrialDictionary { get; set; }
public virtual DbSet<TrialStatusDetail> TrialDetail { get; set; }
public virtual DbSet<TrialUser> UserTrial { get; set; }
public virtual DbSet<TrialDictionary> ProjectDictionary { get; set; }
public virtual DbSet<TrialSiteUser> UserTrialSite { get; set; }
public virtual DbSet<TrialSite> TrialSite { get; set; }
public virtual DbSet<Site> Site { get; set; }
public virtual DbSet<User> User { get; set; }
public virtual DbSet<TrialSiteUserSurvey> TrialSiteUserSurvey { get; set; }
public virtual DbSet<TrialSiteEquipmentSurvey> TrialSiteEquipmentSurvey { get; set; }
public virtual DbSet<TrialSiteSurvey> TrialSiteSurvey { get; set; }
public virtual DbSet<StudyStatusDetail> StudyStatusDetails { get; set; }
#endregion
#region Financial
public virtual DbSet<ReviewerPayInformation> ReviewerPayInformation { get; set; }
public virtual DbSet<RankPrice> RankPrice { get; set; }
public virtual DbSet<TrialPaymentPrice> TrialPaymentPrice { get; set; }
public virtual DbSet<VolumeReward> AwardPrice { get; set; }
public virtual DbSet<Payment> Payment { get; set; }
public virtual DbSet<PaymentDetail> PaymentDetail { get; set; }
public virtual DbSet<ExchangeRate> ExchangeRate { get; set; }
public virtual DbSet<TrialRevenuesPrice> TrialRevenuesPrice { get; set; }
public virtual DbSet<PaymentAdjustment> PaymentAdjustment { get; set; }
public virtual DbSet<TrialRevenuesPriceVerification> TrialRevenuesPriceVerification { get; set; }
#endregion
#region QC
public virtual DbSet<TrialQCQuestion> TrialQCQuestionConfigure { get; set; }
public virtual DbSet<QCQuestion> QCQuestionConfigure { get; set; }
public virtual DbSet<TrialQCQuestionAnswer> TrialQCQuestionAnswer { get; set; }
public virtual DbSet<CheckChallengeDialog> CheckChallengeDialog { get; set; }
#endregion
#region QA
public virtual DbSet<QCChallengeDialog> QCChallengeDialog { get; set; }
public virtual DbSet<QANotice> QATemplateDictionary { get; set; }
public virtual DbSet<QCChallenge> QCChallenge { get; set; }
public virtual DbSet<SubjectVisit> SubjectVisit { get; set; }
#endregion
#region 工作量分配
public virtual DbSet<WorkloadTP> WorkloadTPs { get; set; }
public virtual DbSet<WorkloadGlobal> WorkloadGlobals { get; set; }
public virtual DbSet<WorkloadAD> WorkloadADs { get; set; }
public virtual DbSet<WorkloadDetail> WorkloadDetails { get; set; }
#endregion
#region Document
public virtual DbSet<SystemDocument> SystemDocument { get; set; }
public virtual DbSet<TrialDocument> TrialDocument { get; set; }
public virtual DbSet<TrialDocNeedConfirmedUserType> TrialDocUserTypeConfirm { get; set; }
public virtual DbSet<SystemDocConfirmedUser> SystemDocConfirmedUser { get; set; }
public virtual DbSet<SystemDocNeedConfirmedUserType> SystemDocNeedConfirmedUserType { get; set; }
public virtual DbSet<TrialDocNeedConfirmedUserType> TrialDocNeedConfirmedUserType { get; set; }
public virtual DbSet<TrialDocUserTypeConfirmedUser> TrialDocUserTypeConfirmUser { get; set; }
#endregion
#region 暂时未用
public virtual DbSet<Message> SysMessages { get; set; }
public virtual DbSet<TrialAttachment> TrialAttachment { get; set; }
public virtual DbSet<SystemLog> SystemLogs { get; set; }
public virtual DbSet<TU> TU { get; set; }
public virtual DbSet<TR> TR { get; set; }
public virtual DbSet<RS> RS { get; set; }
public virtual DbSet<Report> Reports { get; set; }
public virtual DbSet<StudyReviewer> StudyReviewer { get; set; }
public virtual DbSet<KeyInstance> KeyInstances { get; set; }
public virtual DbSet<GlobalRS> GlobalRS { get; set; }
public virtual DbSet<GlobalResult> GlobalResult { get; set; }
public virtual DbSet<ImageLabel> ImageLabels { get; set; }
//public virtual DbSet<QATemplateItem> QaTemplateItem { get; set; }
//public virtual DbSet<QATemplateItemDictionary> QaTemplateItemDictionary { get; set; }
//public virtual DbSet<QATemplateTemplateItem> QaTemplateTemplateItem { get; set; }
//public virtual DbSet<QATrialTemplate> QATrailTemplate { get; set; }
//public virtual DbSet<QATrialTemplateItem> QATrialTemplateItem { get; set; }
//public virtual DbSet<QAAboutTrialTemplateItem> QARecordTrialTemplateItem { get; set; }
//public virtual DbSet<QARecordTemplateItemDetail> QARecordTemplateItemDetail { get; set; }
//public virtual DbSet<QATemplate> QATemplate { get; set; }
public virtual DbSet<QANoticeUser> QANoticeUser { get; set; }
public virtual DbSet<QANotice> QANotice { get; set; }
#endregion
public virtual DbSet<EmailNoticeConfig> EmailNoticeConfig { get; set; }
public virtual DbSet<SystemBasicData> SystemBasicData { get; set; }
public virtual DbSet<TrialSign> TrialSign { get; set; }
public virtual DbSet<TrialStateChange> TrialStateChange { get; set; }
public virtual DbSet<SystemAnonymization> SystemAnonymization { get; set; }
public virtual DbSet<TrialExternalUser> TrialExternalUser { get; set; }
public virtual DbSet<UserTypeGroup> UserTypeGroup { get; set; }
public virtual DbSet<DataInspection> DataInspection { get; set; }
public virtual DbSet<TrialUserPreparation> TrialUserPreparation { get; set; }
public virtual DbSet<FrontAuditConfig> FrontAuditConfig { get; set; }
public virtual DbSet<ConsistencyCheckFile> ConsistencyCheckFile { get; set; }
public virtual DbSet<CommonDocument> CommonDocument { get; set; }
public virtual DbSet<SystemNotice> SystemNotice { get; set; }
public virtual DbSet<SystemNoticeUserRead> SystemNoticeUserRead { get; set; }
public virtual DbSet<SystemNoticeUserType> SystemNoticeUserType { get; set; }
#region 废弃
public override int SaveChanges()
{
//UpdateAuditInfo().GetAwaiter();
AddAudit().GetAwaiter();
return base.SaveChanges();
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
//await UpdateAuditInfo();
await AddAudit();
return await base.SaveChangesAsync(cancellationToken);
}
public async Task AddAudit()
{
try
{
var entities = ChangeTracker.Entries().Where(u => (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added)).Where(x => x.Entity.GetType() != typeof(DataInspection)).ToList();
AuditingData auditingData = new AuditingData(this, _userInfo);
await auditingData.IncomingEntitys(entities);
}
catch (Exception)
{
}
}
/// <summary>
/// 重写savechange方式 统一增加审计信息 CreateUserId CreateTime UpdateTime UpdateUserId 可用事件绑定的方式UpdateAuitUser
/// </summary>
//private async Task UpdateAuditInfo()
//{
//ChangeTracker.DetectChanges(); // Important!
//// 获取所有更改,删除,新增的实体,但排除审计实体(避免死循环)
//var entities = ChangeTracker.Entries()
// .Where(u => (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added)).Where(x=>x.Entity.GetType()!=typeof(data)).ToList();
//AuditingData auditingData = new AuditingData(this, _userInfo);
//await auditingData.IncomingEntitys(entities);
//var items = entities.SelectMany(x => x.Entity.GetType().ToString());
//foreach (var t in entities)
//{
// switch (t.State)
// {
// case EntityState.Deleted:
// break;
// case EntityState.Modified:
// if (t.Entity is IAuditUpdate updateEntity1)
// {
// updateEntity1.UpdateTime = DateTime.UtcNow.AddHours(8);
// updateEntity1.UpdateUserId = _userInfo.Id;
// }
// break;
// //添加的时候,更新审计字段也赋值
// case EntityState.Added:
// ////// 仓储添加时 就有id了
// //if (t.Entity is Entity entity && entity.Id == Guid.Empty)
// //{
// // entity.Id = NewId.NextGuid();
// //}
// if (t.Entity is IAuditAdd addEntity)
// {
// if (addEntity.CreateTime == default(DateTime))
// {
// addEntity.CreateTime = DateTime.UtcNow.AddHours(8);
// }
// addEntity.CreateUserId = _userInfo.Id;
// }
// if (t.Entity is IAuditUpdate updateEntity)
// {
// updateEntity.UpdateTime = DateTime.UtcNow.AddHours(8);
// updateEntity.UpdateUserId = _userInfo.Id;
// }
// if (t.Entity is IAuditAddWithUserName addEntity3)
// {
// addEntity3.CreateTime = DateTime.UtcNow.AddHours(8);
// addEntity3.CreateUserId = _userInfo.Id;
// addEntity3.CreateUser = _userInfo.RealName;
// }
// break;
// }
//}
//}
/// <summary>
/// 事件绑定的方式 更新审计信息 废弃
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UpdateAuitUser(object sender, EntityEntryEventArgs e)
{
if (e.Entry.Entity is IAuditUpdate updateEntity)
{
switch (e.Entry.State)
{
//case EntityState.Deleted:
// entityWithTimestamps.UpdateTime = DateTime.UtcNow;
// Console.WriteLine($"Stamped for delete: {e.Entry.Entity}");
// break;
case EntityState.Modified:
updateEntity.UpdateTime = DateTime.UtcNow;
updateEntity.UpdateUserId = _userInfo.Id;
break;
//添加的时候,更新审计字段也赋值
case EntityState.Added:
updateEntity.UpdateTime = DateTime.UtcNow;
updateEntity.UpdateUserId = _userInfo.Id;
break;
}
}
if (e.Entry.Entity is IAuditAdd addEntity)
{
switch (e.Entry.State)
{
case EntityState.Added:
addEntity.CreateTime = DateTime.UtcNow;
addEntity.CreateUserId = _userInfo.Id;
break;
}
}
if (e.Entry.Entity is IAuditAddWithUserName addEntity2)
{
switch (e.Entry.State)
{
case EntityState.Added:
addEntity2.CreateTime = DateTime.UtcNow;
addEntity2.CreateUserId = _userInfo.Id;
addEntity2.CreateUser = _userInfo.RealName;
break;
case EntityState.Deleted:
addEntity2.CreateTime = DateTime.UtcNow;
addEntity2.CreateUserId = _userInfo.Id;
addEntity2.CreateUser = _userInfo.RealName;
break;
}
}
}
#endregion
}
public class MySequentialGuidValueGenerator : ValueGenerator<Guid>
{
public override Guid Next(EntityEntry entry)
{
return NewId.NextGuid();
}
public override bool GeneratesTemporaryValues => false;
}
}