diff --git a/IRaCIS.Core.API/IRaCIS - Backup.Core.API.csproj b/IRaCIS.Core.API/IRaCIS - Backup.Core.API.csproj deleted file mode 100644 index b14f8c9bf..000000000 --- a/IRaCIS.Core.API/IRaCIS - Backup.Core.API.csproj +++ /dev/null @@ -1,107 +0,0 @@ - - - - net6.0 - false - 354572d4-9e15-4099-807c-63a2d29ff9f2 - default - Linux - - - - .\IRaCIS.Core.API.xml - 1701;1702;1591; - ..\bin\ - - - - bin\Release\IRaCIS.Core.API.xml - bin\Release\ - 1701;1702;1591 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Client - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - - - - - - - - - - Always - - - - - - - diff --git a/IRaCIS.Core.API/IRaCIS.Core.API.csproj b/IRaCIS.Core.API/IRaCIS.Core.API.csproj index d73c5fbc1..1a7f28ec4 100644 --- a/IRaCIS.Core.API/IRaCIS.Core.API.csproj +++ b/IRaCIS.Core.API/IRaCIS.Core.API.csproj @@ -96,6 +96,12 @@ + + + Always + + + diff --git a/IRaCIS.Core.API/IRaCIS.Core.API.xml b/IRaCIS.Core.API/IRaCIS.Core.API.xml index 6573bf84a..4402bc0b9 100644 --- a/IRaCIS.Core.API/IRaCIS.Core.API.xml +++ b/IRaCIS.Core.API/IRaCIS.Core.API.xml @@ -375,11 +375,6 @@ 序列化成员 - - - 废弃,没用 - - 对称可逆加密 diff --git a/IRaCIS.Core.API/Middleware/TimeZoneAdjustmentMiddleware.cs b/IRaCIS.Core.API/Middleware/TimeZoneAdjustmentMiddleware.cs deleted file mode 100644 index c3c71da2a..000000000 --- a/IRaCIS.Core.API/Middleware/TimeZoneAdjustmentMiddleware.cs +++ /dev/null @@ -1,118 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Primitives; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Threading.Tasks; - -/// -/// 废弃,没用 -/// -public class TimeZoneAdjustmentMiddleware -{ - private readonly RequestDelegate _next; - - public TimeZoneAdjustmentMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext context) - { - if (string.IsNullOrEmpty(context.Request.ContentType)) - { - // 请求没有内容体,可能是一个没有请求体的请求,比如 GET 请求 - await _next(context); - return; - } - - - var timeZoneId = "Asia/Shanghai"; // 客户端默认时区 - - var timeZoneIdHeaderValue = context.Request.Headers["TimeZoneId"]; - - if (!string.IsNullOrEmpty(timeZoneIdHeaderValue)) - { - timeZoneId = timeZoneIdHeaderValue; - } - - var timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); - - - - // 处理 JSON 请求体中的时间字段 - if (context.Request.ContentType.StartsWith("application/json")) - { - var requestBody = await new StreamReader(context.Request.Body).ReadToEndAsync(); - - // 使用 JSON.NET 或 System.Text.Json 解析 JSON 请求体 - // 假设请求体中有一个名为 "dateTime" 的时间字段 - dynamic jsonData = JsonConvert.DeserializeObject(requestBody); - - if (jsonData.dateTime != null) - { - if (DateTime.TryParse((string)jsonData.dateTime, out DateTime dateTime)) - { - // 将 JSON 请求体中的时间字段转换为服务器时区的时间 - var serverTime = TimeZoneInfo.ConvertTime(dateTime, timeZone); - jsonData.dateTime = serverTime; - } - } - - // 将修改后的 JSON 请求体重新写入请求流中 - var jsonBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(jsonData)); - context.Request.Body = new MemoryStream(jsonBytes); - context.Request.ContentLength = jsonBytes.Length; - } - - - // 处理 URL 表单参数 - var modifiedQuery = new Dictionary(); - - foreach (var key in context.Request.Query.Keys) - { - if (DateTime.TryParse(context.Request.Query[key], out DateTime dateTime)) - { - // 将 URL 表单参数中的时间转换为服务器时区的时间 - var serverTime = TimeZoneInfo.ConvertTime(dateTime, timeZone); - modifiedQuery[key] = new StringValues(serverTime.ToString()); - } - else - { - modifiedQuery[key] = context.Request.Query[key]; - } - } - - context.Request.Query = new QueryCollection(modifiedQuery); - - // 处理Form请求体中的参数 - if (context.Request.HasFormContentType) - { - var modifiedForm = new Dictionary(); - - foreach (var key in context.Request.Form.Keys) - { - if (DateTime.TryParse(context.Request.Form[key], out DateTime dateTime)) - { - // 将请求体中的时间转换为服务器时区的时间 - var serverTime = TimeZoneInfo.ConvertTime(dateTime, timeZone); - modifiedForm[key] = new StringValues(serverTime.ToString()); - } - else - { - modifiedForm[key] = context.Request.Form[key]; - } - } - - var newFormCollection = new FormCollection(modifiedForm); - - // 将新的表单集合设置回请求对象 - context.Request.Form = newFormCollection; - } - - await _next(context); - } - -} diff --git a/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs index a6e0352d5..176ea178c 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs @@ -8,9 +8,11 @@ using Medallion.Threading; using Medallion.Threading.SqlServer; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using StackExchange.Redis; namespace IRaCIS.Core.API @@ -46,10 +48,11 @@ namespace IRaCIS.Core.API else { options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure()); - } + //迁移的时候,不生成外键 + options.ReplaceService(); options.UseLoggerFactory(logFactory); diff --git a/IRaCIS.Core.API/appsettings.json b/IRaCIS.Core.API/appsettings.json index 75bc653af..dec14286d 100644 --- a/IRaCIS.Core.API/appsettings.json +++ b/IRaCIS.Core.API/appsettings.json @@ -43,40 +43,6 @@ } ] }, - "easycaching": { - "inmemory": { - "MaxRdSecond": 120, - "EnableLogging": false, - "LockMs": 5000, - "SleepMs": 300, - "DBConfig": { - "SizeLimit": 10000, - "ExpirationScanFrequency": 60, - "EnableReadDeepClone": true, - "EnableWriteDeepClone": false - } - }, - "redis": { - "MaxRdSecond": 120, - "EnableLogging": false, - "LockMs": 5000, - "SleepMs": 300, - "dbconfig": { - "Password": "xc@123456", - "IsSsl": false, - "SslHost": null, - "ConnectionTimeout": 5000, - "AllowAdmin": true, - "Endpoints": [ - { - "Host": "47.117.164.182", - "Port": 6379 - } - ], - "Database": 0 - } - } - }, "IRaCISImageStore": { "SwitchingMode": "RemainingDiskCapacity", "SwitchingRatio": 80, @@ -93,7 +59,6 @@ "DefaultPassword": "123456", "ImageShareExpireDays": 10 }, - "EncrypteResponseConfig": { "IsEnable": true, "ApiPathList": [ diff --git a/IRaCIS.Core.Infra.EFCore/CodeFirst使用说明 b/IRaCIS.Core.Infra.EFCore/CodeFirst使用说明 new file mode 100644 index 000000000..c5e75d12e --- /dev/null +++ b/IRaCIS.Core.Infra.EFCore/CodeFirst使用说明 @@ -0,0 +1,19 @@ + + + +# ̨ʹ÷ʽ + +1Ǩļ +add-migration init -Context IRaCISDBContext + + + + + + +# ʹdotnet Ǩ + +# dotnet ef migrations add Ǩ -p Ŀ -c ݿ -o ǨļĿ¼ + +1Ǩļ +dotnet ef migrations add Initial -s IRaCIS.Core.API -p IRaCIS.Core.Infra.EFCore -c IRaCISDBContext -o CodeFirst_MSSQL/Migrations diff --git a/IRaCIS.Core.Infra.EFCore/Context/Convention/DecimalPrecisionConvention.cs b/IRaCIS.Core.Infra.EFCore/Context/Convention/DecimalPrecisionConvention.cs new file mode 100644 index 000000000..9b473d1cf --- /dev/null +++ b/IRaCIS.Core.Infra.EFCore/Context/Convention/DecimalPrecisionConvention.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Microsoft.EntityFrameworkCore.Metadata.Conventions; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IRaCIS.Core.Infra.EFCore; + + +public class DecimalPrecisionConvention : IModelFinalizingConvention +{ + private readonly int _precision; + private readonly int _scale; + + public DecimalPrecisionConvention(int precision, int scale) + { + _precision = precision; + _scale = scale; + } + + public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext context) + { + + foreach (var property in modelBuilder.Metadata.GetEntityTypes() + .SelectMany( + entityType => entityType.GetDeclaredProperties() + .Where( + property => property.ClrType == typeof(decimal) || property.ClrType == typeof(decimal?)))) + { + + + // 设置精度和小数位数 + property.SetPrecision(_precision); + property.SetScale(_scale); + } + } +} diff --git a/IRaCIS.Core.Infra.EFCore/Context/Convention/DefaultStringLengthConvention .cs b/IRaCIS.Core.Infra.EFCore/Context/Convention/DefaultStringLengthConvention .cs new file mode 100644 index 000000000..1e5845ef8 --- /dev/null +++ b/IRaCIS.Core.Infra.EFCore/Context/Convention/DefaultStringLengthConvention .cs @@ -0,0 +1,56 @@ +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Microsoft.EntityFrameworkCore.Metadata.Conventions; +using System; +using System.ComponentModel.DataAnnotations; +using System.Linq; + +namespace IRaCIS.Core.Infra.EFCore; + +/// +/// Efcore 最新支持批量配置字符串类型长度作为保底的 官网参考:https://learn.microsoft.com/zh-cn/ef/core/modeling/bulk-configuration#conventions +/// 设置不标注,默认长度,然后标注了与默认长度不一致,那么就是以标注的为准,同时如果标注了MaxLength ,对于mssql 那就是nvarcharMax,对于pgsql 就是text +/// +public class DefaultStringLengthConvention : IModelFinalizingConvention +{ + private readonly int _defaultLenth; + + public DefaultStringLengthConvention(int defaultLenth) + { + _defaultLenth = defaultLenth; + } + + public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext context) + { + foreach (var property in modelBuilder.Metadata.GetEntityTypes() + .SelectMany( + entityType => entityType.GetDeclaredProperties() + .Where( + property => property.ClrType == typeof(string)))) + { + + // 获取 MaxLength 特性 + var maxLengthAttribute = property.PropertyInfo?.GetCustomAttributes(typeof(MaxLengthAttribute), false) + .FirstOrDefault() as MaxLengthAttribute; + + // 获取 StringLength 特性 + var stringLengthAttribute = property.PropertyInfo?.GetCustomAttributes(typeof(StringLengthAttribute), false) + .FirstOrDefault() as StringLengthAttribute; + + // 输出调试信息,看看是哪种特性生效 + if (stringLengthAttribute != null) + { + //Console.WriteLine($"{property.Name}: StringLength({stringLengthAttribute.MaximumLength})"); + property.Builder.HasMaxLength(stringLengthAttribute.MaximumLength); + } + else if (maxLengthAttribute != null) + { + //Console.WriteLine($"{property.Name}: MaxLength (no specific length, allowing max)"); + } + else + { + //Console.WriteLine($"{property.Name}: Default length 200"); + property.Builder.HasMaxLength(_defaultLenth); + } + } + } +} diff --git a/IRaCIS.Core.Infra.EFCore/Context/Convention/NoForeignKeyMigrationsSqlGenerator.cs b/IRaCIS.Core.Infra.EFCore/Context/Convention/NoForeignKeyMigrationsSqlGenerator.cs new file mode 100644 index 000000000..7603b8e06 --- /dev/null +++ b/IRaCIS.Core.Infra.EFCore/Context/Convention/NoForeignKeyMigrationsSqlGenerator.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; + +namespace IRaCIS.Core.Infra.EFCore; + + +/// +/// 迁移的时候,忽略显示外键的建立,增加灵活性,同时为了兼容之前dbfirst 一个字段关联多个表 +/// +public class NoForeignKeyMigrationsSqlGenerator : MigrationsSqlGenerator +{ + public NoForeignKeyMigrationsSqlGenerator( + MigrationsSqlGeneratorDependencies dependencies) : base(dependencies) + { + } + + protected override void Generate(Microsoft.EntityFrameworkCore.Migrations.Operations.CreateTableOperation operation, IModel? model, MigrationCommandListBuilder builder, bool terminate = true) + { + operation.ForeignKeys.Clear(); + base.Generate(operation, model, builder, terminate); + } +} diff --git a/IRaCIS.Core.Infra.EFCore/Context/DbContextExt.cs b/IRaCIS.Core.Infra.EFCore/Context/DbContextExt.cs index 0eb9ee82a..88d80e112 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/DbContextExt.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/DbContextExt.cs @@ -5,246 +5,245 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -namespace IRaCIS.Core.Infra.EFCore +namespace IRaCIS.Core.Infra.EFCore; + +public static class DbContextExt { - public static class DbContextExt + + /// + /// 获取变化的实体信息 + /// + /// + /// + /// + public static IEnumerable GetChanges(this DbContext db) { - - /// - /// 获取变化的实体信息 - /// - /// - /// - /// - public static IEnumerable GetChanges(this DbContext db) + return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified && e.Entity is T).Select(e => { - return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified && e.Entity is T).Select(e => + var originalObject = e.OriginalValues.ToObject(); + var currentObject = e.CurrentValues.ToObject(); + return new ChangeEntry { - var originalObject = e.OriginalValues.ToObject(); - var currentObject = e.CurrentValues.ToObject(); - return new ChangeEntry + EntityState = e.State, + Entity = e.Entity, + EntityType = e.OriginalValues.EntityType.ClrType, + ChangeProperties = e.OriginalValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(originalObject))).Zip(e.CurrentValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(currentObject))), (t1, t2) => new ChangePropertyInfo() { - EntityState = e.State, - Entity = e.Entity, - EntityType = e.OriginalValues.EntityType.ClrType, - ChangeProperties = e.OriginalValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(originalObject))).Zip(e.CurrentValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(currentObject))), (t1, t2) => new ChangePropertyInfo() - { - PropertyInfo = t1.Property.PropertyInfo, - OriginalValue = t1.Value, - CurrentValue = t2.Value, - IsPrimaryKey = t1.Property.IsPrimaryKey(), - IsForeignKey = t1.Property.IsForeignKey() - }).Where(t => Comparer.Default.Compare(t.OriginalValue, t.CurrentValue) != 0).ToList() - }; - }); - } - - - - /// - /// 获取变化的实体信息 - /// - /// - /// - public static IEnumerable GetChanges(this DbContext db) - { - return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified).Select(e => - { - var originalObject = e.OriginalValues.ToObject(); - var currentObject = e.CurrentValues.ToObject(); - return new ChangeEntry() - { - EntityState = e.State, - Entity = e.Entity, - EntityType = e.OriginalValues.EntityType.ClrType, - ChangeProperties = e.OriginalValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(originalObject))).Zip(e.CurrentValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(currentObject))), (t1, t2) => new ChangePropertyInfo() - { - PropertyInfo = t1.Property.PropertyInfo, - OriginalValue = t1.Value, - CurrentValue = t2.Value, - IsPrimaryKey = t1.Property.IsPrimaryKey(), - IsForeignKey = t1.Property.IsForeignKey(), - }).Where(t => Comparer.Default.Compare(t.OriginalValue, t.CurrentValue) != 0).ToList() - }; - }); - } - - /// - /// 获取添加的实体信息 - /// - /// - /// - /// - public static IEnumerable GetAdded(this DbContext db) - { - return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Added && e.Entity is T).Select(e => - { - var currentObject = e.CurrentValues.ToObject(); - return new ChangeEntry - { - EntityState = e.State, - Entity = e.Entity, - EntityType = e.CurrentValues.EntityType.ClrType, - ChangeProperties = e.CurrentValues.Properties.Select(p => new ChangePropertyInfo() - { - PropertyInfo = p.PropertyInfo, - CurrentValue = p.PropertyInfo.GetValue(currentObject), - IsPrimaryKey = p.IsPrimaryKey(), - IsForeignKey = p.IsForeignKey(), - }).ToList() - }; - }); - } - - /// - /// 获取添加的实体信息 - /// - /// - /// - public static IEnumerable GetAdded(this DbContext db) - { - return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Added).Select(e => - { - var currentObject = e.CurrentValues.ToObject(); - return new ChangeEntry - { - EntityState = e.State, - Entity = e.Entity, - EntityType = e.CurrentValues.EntityType.ClrType, - ChangeProperties = e.CurrentValues.Properties.Select(p => new ChangePropertyInfo() - { - PropertyInfo = p.PropertyInfo, - CurrentValue = p.PropertyInfo.GetValue(currentObject), - IsPrimaryKey = p.IsPrimaryKey(), - IsForeignKey = p.IsForeignKey(), - }).ToList() - }; - }); - } - - /// - /// 获取移除的实体信息 - /// - /// - /// - /// - public static IEnumerable GetRemoved(this DbContext db) - { - return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted && e.Entity is T).Select(e => - { - var originalObject = e.OriginalValues.ToObject(); - return new ChangeEntry - { - EntityState = e.State, - Entity = e.Entity, - EntityType = e.OriginalValues.EntityType.ClrType, - ChangeProperties = e.OriginalValues.Properties.Select(p => new ChangePropertyInfo() - { - PropertyInfo = p.PropertyInfo, - OriginalValue = p.PropertyInfo.GetValue(originalObject), - IsPrimaryKey = p.IsPrimaryKey(), - IsForeignKey = p.IsForeignKey(), - }).ToList() - }; - }); - } - - /// - /// 获取移除的实体信息 - /// - /// - /// - public static IEnumerable GetRemoved(this DbContext db) - { - return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted).Select(e => - { - var originalObject = e.OriginalValues.ToObject(); - return new ChangeEntry - { - EntityState = e.State, - Entity = e.Entity, - EntityType = e.OriginalValues.EntityType.ClrType, - ChangeProperties = e.OriginalValues.Properties.Select(p => new ChangePropertyInfo() - { - PropertyInfo = p.PropertyInfo, - OriginalValue = p.PropertyInfo.GetValue(originalObject), - IsPrimaryKey = p.IsPrimaryKey(), - IsForeignKey = p.IsForeignKey(), - }).ToList() - }; - }); - } - - /// - /// 获取所有的变更信息 - /// - /// - /// - /// - public static IEnumerable GetAllChanges(this DbContext db) - { - return GetChanges(db).Union(GetAdded(db)).Union(GetRemoved(db)); - } - - /// - /// 获取所有的变更信息 - /// - /// - /// - public static IEnumerable GetAllChanges(this DbContext db) - { - return GetChanges(db).Union(GetAdded(db)).Union(GetRemoved(db)); - } + PropertyInfo = t1.Property.PropertyInfo, + OriginalValue = t1.Value, + CurrentValue = t2.Value, + IsPrimaryKey = t1.Property.IsPrimaryKey(), + IsForeignKey = t1.Property.IsForeignKey() + }).Where(t => Comparer.Default.Compare(t.OriginalValue, t.CurrentValue) != 0).ToList() + }; + }); } - public class ChangePropertyInfo + + + /// + /// 获取变化的实体信息 + /// + /// + /// + public static IEnumerable GetChanges(this DbContext db) { - /// - /// 属性 - /// - public PropertyInfo PropertyInfo { get; set; } - - /// - /// 原始值 - /// - public object OriginalValue { get; set; } - - /// - /// 新值 - /// - public object CurrentValue { get; set; } - - /// - /// 是否是主键 - /// - public bool IsPrimaryKey { get; set; } - - /// - /// 是否是外键 - /// - public bool IsForeignKey { get; set; } + return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified).Select(e => + { + var originalObject = e.OriginalValues.ToObject(); + var currentObject = e.CurrentValues.ToObject(); + return new ChangeEntry() + { + EntityState = e.State, + Entity = e.Entity, + EntityType = e.OriginalValues.EntityType.ClrType, + ChangeProperties = e.OriginalValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(originalObject))).Zip(e.CurrentValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(currentObject))), (t1, t2) => new ChangePropertyInfo() + { + PropertyInfo = t1.Property.PropertyInfo, + OriginalValue = t1.Value, + CurrentValue = t2.Value, + IsPrimaryKey = t1.Property.IsPrimaryKey(), + IsForeignKey = t1.Property.IsForeignKey(), + }).Where(t => Comparer.Default.Compare(t.OriginalValue, t.CurrentValue) != 0).ToList() + }; + }); } - public class ChangeEntry + /// + /// 获取添加的实体信息 + /// + /// + /// + /// + public static IEnumerable GetAdded(this DbContext db) { - /// - /// 所属实体 - /// - public object Entity { get; set; } - - /// - /// 实体类型 - /// - public Type EntityType { get; set; } - - /// - /// 变更类型 - /// - public EntityState EntityState { get; set; } - - /// - /// 字段变更信息 - /// - public List ChangeProperties { get; set; } + return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Added && e.Entity is T).Select(e => + { + var currentObject = e.CurrentValues.ToObject(); + return new ChangeEntry + { + EntityState = e.State, + Entity = e.Entity, + EntityType = e.CurrentValues.EntityType.ClrType, + ChangeProperties = e.CurrentValues.Properties.Select(p => new ChangePropertyInfo() + { + PropertyInfo = p.PropertyInfo, + CurrentValue = p.PropertyInfo.GetValue(currentObject), + IsPrimaryKey = p.IsPrimaryKey(), + IsForeignKey = p.IsForeignKey(), + }).ToList() + }; + }); } + + /// + /// 获取添加的实体信息 + /// + /// + /// + public static IEnumerable GetAdded(this DbContext db) + { + return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Added).Select(e => + { + var currentObject = e.CurrentValues.ToObject(); + return new ChangeEntry + { + EntityState = e.State, + Entity = e.Entity, + EntityType = e.CurrentValues.EntityType.ClrType, + ChangeProperties = e.CurrentValues.Properties.Select(p => new ChangePropertyInfo() + { + PropertyInfo = p.PropertyInfo, + CurrentValue = p.PropertyInfo.GetValue(currentObject), + IsPrimaryKey = p.IsPrimaryKey(), + IsForeignKey = p.IsForeignKey(), + }).ToList() + }; + }); + } + + /// + /// 获取移除的实体信息 + /// + /// + /// + /// + public static IEnumerable GetRemoved(this DbContext db) + { + return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted && e.Entity is T).Select(e => + { + var originalObject = e.OriginalValues.ToObject(); + return new ChangeEntry + { + EntityState = e.State, + Entity = e.Entity, + EntityType = e.OriginalValues.EntityType.ClrType, + ChangeProperties = e.OriginalValues.Properties.Select(p => new ChangePropertyInfo() + { + PropertyInfo = p.PropertyInfo, + OriginalValue = p.PropertyInfo.GetValue(originalObject), + IsPrimaryKey = p.IsPrimaryKey(), + IsForeignKey = p.IsForeignKey(), + }).ToList() + }; + }); + } + + /// + /// 获取移除的实体信息 + /// + /// + /// + public static IEnumerable GetRemoved(this DbContext db) + { + return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted).Select(e => + { + var originalObject = e.OriginalValues.ToObject(); + return new ChangeEntry + { + EntityState = e.State, + Entity = e.Entity, + EntityType = e.OriginalValues.EntityType.ClrType, + ChangeProperties = e.OriginalValues.Properties.Select(p => new ChangePropertyInfo() + { + PropertyInfo = p.PropertyInfo, + OriginalValue = p.PropertyInfo.GetValue(originalObject), + IsPrimaryKey = p.IsPrimaryKey(), + IsForeignKey = p.IsForeignKey(), + }).ToList() + }; + }); + } + + /// + /// 获取所有的变更信息 + /// + /// + /// + /// + public static IEnumerable GetAllChanges(this DbContext db) + { + return GetChanges(db).Union(GetAdded(db)).Union(GetRemoved(db)); + } + + /// + /// 获取所有的变更信息 + /// + /// + /// + public static IEnumerable GetAllChanges(this DbContext db) + { + return GetChanges(db).Union(GetAdded(db)).Union(GetRemoved(db)); + } +} + +public class ChangePropertyInfo +{ + /// + /// 属性 + /// + public PropertyInfo PropertyInfo { get; set; } + + /// + /// 原始值 + /// + public object OriginalValue { get; set; } + + /// + /// 新值 + /// + public object CurrentValue { get; set; } + + /// + /// 是否是主键 + /// + public bool IsPrimaryKey { get; set; } + + /// + /// 是否是外键 + /// + public bool IsForeignKey { get; set; } +} + +public class ChangeEntry +{ + /// + /// 所属实体 + /// + public object Entity { get; set; } + + /// + /// 实体类型 + /// + public Type EntityType { get; set; } + + /// + /// 变更类型 + /// + public EntityState EntityState { get; set; } + + /// + /// 字段变更信息 + /// + public List ChangeProperties { get; set; } } \ No newline at end of file diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index 47b7795e9..5eeb22984 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -25,512 +25,520 @@ using System.Collections.Generic; using System.ComponentModel; using Microsoft.VisualBasic; -namespace IRaCIS.Core.Infra.EFCore +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 { - #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(200)); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + #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 - public IRaCISDBContext(DbContextOptions options) : base(options) + //遍历实体模型手动配置 + 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); - protected override void OnModelCreating(ModelBuilder modelBuilder) + foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { - #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 - - //遍历实体模型手动配置 - var typesToRegister = Assembly.GetExecutingAssembly().GetTypes().Where(q => q.GetInterface(typeof(IEntityTypeConfiguration<>).FullName) != null); - foreach (var type in typesToRegister) + // 软删除配置 + if (typeof(ISoftDelete).IsAssignableFrom(entityType.ClrType)) { - dynamic configurationInstance = Activator.CreateInstance(type); - modelBuilder.ApplyConfiguration(configurationInstance); + entityType.AddSoftDeleteQueryFilter(); + } - base.OnModelCreating(modelBuilder); - - foreach (var entityType in modelBuilder.Model.GetEntityTypes()) + if (typeof(Entity).IsAssignableFrom(entityType.ClrType)) { - // 软删除配置 - if (typeof(ISoftDelete).IsAssignableFrom(entityType.ClrType)) - { - entityType.AddSoftDeleteQueryFilter(); - - } - - 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(); - } + 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 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 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; } - - - - - #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 未分类 - - 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 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; } - - - } + #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 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 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; } + + + + + #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 未分类 + + 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 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; } + + } \ No newline at end of file diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContextFactory.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContextFactory.cs new file mode 100644 index 000000000..55d07f2f7 --- /dev/null +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContextFactory.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IRaCIS.Core.Infra.EFCore.Context; + + +/// +/// Design-time DbContext Creation 用于迁移时指定使用哪个数据库 +/// +public class IRaCISDBContextFactory : IDesignTimeDbContextFactory +{ + public IRaCISDBContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseSqlServer("Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true", contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure()); + + return new IRaCISDBContext(optionsBuilder.Options); + } +} + diff --git a/IRaCIS.Core.Infra.EFCore/Context/ValueGenerator/MySequentialGuidValueGenerator.cs b/IRaCIS.Core.Infra.EFCore/Context/ValueGenerator/MySequentialGuidValueGenerator.cs index f7aa2956c..7534f6b57 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/ValueGenerator/MySequentialGuidValueGenerator.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/ValueGenerator/MySequentialGuidValueGenerator.cs @@ -4,15 +4,13 @@ using MassTransit; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.ValueGeneration; -namespace IRaCIS.Core.Infra.EFCore -{ - public class MySequentialGuidValueGenerator : ValueGenerator - { - public override Guid Next(EntityEntry entry) - { - return NewId.NextSequentialGuid(); - } - public override bool GeneratesTemporaryValues => false; - } +namespace IRaCIS.Core.Infra.EFCore; +public class MySequentialGuidValueGenerator : ValueGenerator +{ + public override Guid Next(EntityEntry entry) + { + return NewId.NextSequentialGuid(); + } + public override bool GeneratesTemporaryValues => false; } \ No newline at end of file diff --git a/IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj b/IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj index 3d99c723f..60a1b70d4 100644 --- a/IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj +++ b/IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj @@ -25,6 +25,15 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/IRaCIS.Core.Test/CodeFirstTest/CodeFirst使用说明 b/IRaCIS.Core.Test/CodeFirstTest/CodeFirst使用说明 index 0693d6509..8f755d360 100644 --- a/IRaCIS.Core.Test/CodeFirstTest/CodeFirst使用说明 +++ b/IRaCIS.Core.Test/CodeFirstTest/CodeFirst使用说明 @@ -20,7 +20,7 @@ https://www.cnblogs.com/cqpanda/p/16815263.html 5ijθµݿǨƣԶִdown dotnet ef database update ijǨƵǰһǨ -p IRaCIS.Core.Test -c IRCContext - dotnet ef migrations add RemoveForeignKey -p IRaCIS.Core.Test -c IRCContext -o CodeFirstTest/MSSQL/Migrations + dotnet ef migrations add RemoveForeignKey -p IRaCIS.Core.Test -c IRCContext -o CodeFirstTest/MSSQL/Migrations diff --git a/IRaCIS.Core.Test/CodeFirstTest/PGSQL/Convention/MaxStringLengthConvention .cs b/IRaCIS.Core.Test/CodeFirstTest/PGSQL/Convention/MaxStringLengthConvention .cs index e59564802..efcbda828 100644 --- a/IRaCIS.Core.Test/CodeFirstTest/PGSQL/Convention/MaxStringLengthConvention .cs +++ b/IRaCIS.Core.Test/CodeFirstTest/PGSQL/Convention/MaxStringLengthConvention .cs @@ -11,6 +11,12 @@ namespace IRaCIS.Core.Test.CodeFirstTest.PGSQL.Migrations /// public class MaxStringLengthConvention : IModelFinalizingConvention { + private readonly int _defaultLenth; + + public MaxStringLengthConvention(int defaultLenth) + { + _defaultLenth = defaultLenth; + } public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext context) { foreach (var property in modelBuilder.Metadata.GetEntityTypes() @@ -31,17 +37,17 @@ namespace IRaCIS.Core.Test.CodeFirstTest.PGSQL.Migrations // 输出调试信息,看看是哪种特性生效 if (stringLengthAttribute != null) { - Console.WriteLine($"{property.Name}: StringLength({stringLengthAttribute.MaximumLength})"); + //Console.WriteLine($"{property.Name}: StringLength({stringLengthAttribute.MaximumLength})"); property.Builder.HasMaxLength(stringLengthAttribute.MaximumLength); } else if (maxLengthAttribute != null) { - Console.WriteLine($"{property.Name}: MaxLength (no specific length, allowing max)"); + //Console.WriteLine($"{property.Name}: MaxLength (no specific length, allowing max)"); } else { - Console.WriteLine($"{property.Name}: Default length 200"); - property.Builder.HasMaxLength(200); + //Console.WriteLine($"{property.Name}: Default length {_defaultLenth}"); + property.Builder.HasMaxLength(_defaultLenth); } } } diff --git a/IRaCIS.Core.Test/CodeFirstTest/PGSQL/PGContext.cs b/IRaCIS.Core.Test/CodeFirstTest/PGSQL/PGContext.cs index 0437fa656..bdd5f6db4 100644 --- a/IRaCIS.Core.Test/CodeFirstTest/PGSQL/PGContext.cs +++ b/IRaCIS.Core.Test/CodeFirstTest/PGSQL/PGContext.cs @@ -70,7 +70,7 @@ public partial class PGContext : DbContext //configurationBuilder.Conventions.Add(_ => new NoForeignKeyConvention()); //针对字符串使用默认的长度配置 - configurationBuilder.Conventions.Add(_ => new MaxStringLengthConvention()); + configurationBuilder.Conventions.Add(_ => new MaxStringLengthConvention(200)); } partial void OnModelCreatingPartial(ModelBuilder modelBuilder); diff --git a/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj b/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj index 9d1a28e03..2bb08de11 100644 --- a/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj +++ b/IRaCIS.Core.Test/IRaCIS.Core.Test.csproj @@ -52,16 +52,11 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/IRaCIS.Core.Test/模板使用说明 b/IRaCIS.Core.Test/模板使用说明 index d8aee69ec..f74d40bb9 100644 --- a/IRaCIS.Core.Test/模板使用说明 +++ b/IRaCIS.Core.Test/模板使用说明 @@ -17,7 +17,7 @@ -c 指定数据库上下文名字 -d 使用数据注解 不指定,默认是fluentAPI -t 指定要生成的表名 --p 指定项目名字 +-p 指定项目名字 (包含上下文,并且产生迁移文件的项目) 备注: 因为是从数据库反向生成实体,所以会默认生成dbcontext ,每次生成想要的实体后,删除指定的名称context即可 针对字符串类型,我们避免string字段 数据库存储null string? 数据库才存储null(除非有合理的理由),这样可以避免代码里面用string 变量,总是要判断是否为null