From ab68a63bdd51d56ac729f23d456bacf25cb48da4 Mon Sep 17 00:00:00 2001
From: hang <87227557@qq.com>
Date: Tue, 17 Sep 2024 14:26:12 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0codefirst=E8=BF=81=E7=A7=BB?=
=?UTF-8?q?=E9=85=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../IRaCIS - Backup.Core.API.csproj | 107 --
IRaCIS.Core.API/IRaCIS.Core.API.csproj | 6 +
IRaCIS.Core.API/IRaCIS.Core.API.xml | 5 -
.../TimeZoneAdjustmentMiddleware.cs | 118 ---
IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs | 5 +-
IRaCIS.Core.API/appsettings.json | 35 -
IRaCIS.Core.Infra.EFCore/CodeFirst使用说明 | 19 +
.../Convention/DecimalPrecisionConvention.cs | 40 +
.../DefaultStringLengthConvention .cs | 56 +
.../NoForeignKeyMigrationsSqlGenerator.cs | 23 +
.../Context/DbContextExt.cs | 459 ++++----
.../Context/IRaCISDBContext.cs | 982 +++++++++---------
.../Context/IRaCISDBContextFactory.cs | 25 +
.../MySequentialGuidValueGenerator.cs | 18 +-
.../IRaCIS.Core.Infra.EFCore.csproj | 9 +
.../CodeFirstTest/CodeFirst使用说明 | 2 +-
.../Convention/MaxStringLengthConvention .cs | 14 +-
.../CodeFirstTest/PGSQL/PGContext.cs | 2 +-
IRaCIS.Core.Test/IRaCIS.Core.Test.csproj | 7 +-
IRaCIS.Core.Test/模板使用说明 | 2 +-
20 files changed, 928 insertions(+), 1006 deletions(-)
delete mode 100644 IRaCIS.Core.API/IRaCIS - Backup.Core.API.csproj
delete mode 100644 IRaCIS.Core.API/Middleware/TimeZoneAdjustmentMiddleware.cs
create mode 100644 IRaCIS.Core.Infra.EFCore/CodeFirst使用说明
create mode 100644 IRaCIS.Core.Infra.EFCore/Context/Convention/DecimalPrecisionConvention.cs
create mode 100644 IRaCIS.Core.Infra.EFCore/Context/Convention/DefaultStringLengthConvention .cs
create mode 100644 IRaCIS.Core.Infra.EFCore/Context/Convention/NoForeignKeyMigrationsSqlGenerator.cs
create mode 100644 IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContextFactory.cs
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