From 096ecdfb84bad3c2afc909fb511794b64d2d359f Mon Sep 17 00:00:00 2001
From: 2881099 <2881099@qq.com>
Date: Mon, 29 Jan 2024 09:17:49 +0800
Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20DbContextOptions.Audit?=
=?UTF-8?q?Value=20=E5=9F=BA=E4=BA=8E=20Ioc=20Scoped=20=E5=AE=A1=E8=AE=A1?=
=?UTF-8?q?=E5=80=BC=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../AggregateRootRepositoryAsync.cs | 23 +-
.../AggregateRootRepositorySync.cs | 23 +-
.../FreeSql.Extensions.AggregateRoot.csproj | 4 +-
.../DbContext/DbContextOptions.cs | 30 ++
FreeSql.DbContext/DbSet/DbSet.cs | 27 +-
FreeSql.DbContext/FreeSql.DbContext.xml | 29 ++
.../UnitOfWork/UnitOfWorkManager.cs | 1 +
FreeSql/Extensions/FreeSqlGlobalExtensions.cs | 1 +
FreeSql/FreeSql.xml | 288 ++++++++++++++++++
9 files changed, 417 insertions(+), 9 deletions(-)
diff --git a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositoryAsync.cs b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositoryAsync.cs
index 97b64bb8..6c2a38e5 100644
--- a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositoryAsync.cs
+++ b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositoryAsync.cs
@@ -263,7 +263,28 @@ namespace FreeSql
}));
}
- var updateLogDict = tracking.UpdateLog.GroupBy(a => a.Item1).ToDictionary(a => a.Key, a => tracking.UpdateLog.Where(b => b.Item1 == a.Key).Select(b => new
+ if (_repository.DbContextOptions.AuditValueHandler != null)
+ {
+ foreach (var log in tracking.UpdateLog)
+ {
+ var table = Orm.CodeFirst.GetTableByEntity(log.Item1);
+ _repository.DbContextOptions.AuditValueHandler(this, new DbContextAuditValueEventArgs(Aop.AuditValueType.Update, log.Item1, log.Item3));
+ log.Item4.Clear();
+ foreach (var col in table.ColumnsByCs.Values)
+ {
+ if (table.ColumnsByCsIgnore.ContainsKey(col.CsName)) continue;
+ if (table.ColumnsByCs.ContainsKey(col.CsName))
+ {
+ if (col.Attribute.IsVersion) continue;
+ var propvalBefore = table.GetPropertyValue(log.Item2, col.CsName);
+ var propvalAfter = table.GetPropertyValue(log.Item3, col.CsName);
+ if (AggregateRootUtils.CompareEntityPropertyValue(col.CsType, propvalBefore, propvalAfter) == false) log.Item4.Add(col.CsName);
+ continue;
+ }
+ }
+ }
+ }
+ var updateLogDict = tracking.UpdateLog.GroupBy(a => a.Item1).ToDictionary(a => a.Key, a => tracking.UpdateLog.Where(b => b.Item1 == a.Key && b.Item4.Any()).Select(b => new
{
BeforeObject = b.Item2,
AfterObject = b.Item3,
diff --git a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositorySync.cs b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositorySync.cs
index 9f747fe7..c6fba292 100644
--- a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositorySync.cs
+++ b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositorySync.cs
@@ -314,7 +314,28 @@ namespace FreeSql
}));
}
- var updateLogDict = tracking.UpdateLog.GroupBy(a => a.Item1).ToDictionary(a => a.Key, a => tracking.UpdateLog.Where(b => b.Item1 == a.Key).Select(b => new
+ if (_repository.DbContextOptions.AuditValueHandler != null)
+ {
+ foreach (var log in tracking.UpdateLog)
+ {
+ var table = Orm.CodeFirst.GetTableByEntity(log.Item1);
+ _repository.DbContextOptions.AuditValueHandler(this, new DbContextAuditValueEventArgs(Aop.AuditValueType.Update, log.Item1, log.Item3));
+ log.Item4.Clear();
+ foreach (var col in table.ColumnsByCs.Values)
+ {
+ if (table.ColumnsByCsIgnore.ContainsKey(col.CsName)) continue;
+ if (table.ColumnsByCs.ContainsKey(col.CsName))
+ {
+ if (col.Attribute.IsVersion) continue;
+ var propvalBefore = table.GetPropertyValue(log.Item2, col.CsName);
+ var propvalAfter = table.GetPropertyValue(log.Item3, col.CsName);
+ if (AggregateRootUtils.CompareEntityPropertyValue(col.CsType, propvalBefore, propvalAfter) == false) log.Item4.Add(col.CsName);
+ continue;
+ }
+ }
+ }
+ }
+ var updateLogDict = tracking.UpdateLog.GroupBy(a => a.Item1).ToDictionary(a => a.Key, a => tracking.UpdateLog.Where(b => b.Item1 == a.Key && b.Item4.Any()).Select(b => new
{
BeforeObject = b.Item2,
AfterObject = b.Item3,
diff --git a/Extensions/FreeSql.Extensions.AggregateRoot/FreeSql.Extensions.AggregateRoot.csproj b/Extensions/FreeSql.Extensions.AggregateRoot/FreeSql.Extensions.AggregateRoot.csproj
index 73705458..f47e0668 100644
--- a/Extensions/FreeSql.Extensions.AggregateRoot/FreeSql.Extensions.AggregateRoot.csproj
+++ b/Extensions/FreeSql.Extensions.AggregateRoot/FreeSql.Extensions.AggregateRoot.csproj
@@ -23,12 +23,12 @@
-
+
-
+
diff --git a/FreeSql.DbContext/DbContext/DbContextOptions.cs b/FreeSql.DbContext/DbContext/DbContextOptions.cs
index 58ad5407..11b5445b 100644
--- a/FreeSql.DbContext/DbContext/DbContextOptions.cs
+++ b/FreeSql.DbContext/DbContext/DbContextOptions.cs
@@ -1,4 +1,5 @@
+using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -47,5 +48,34 @@ namespace FreeSql
/// 实体变化事件
///
public Action> OnEntityChange { get; set; }
+
+ ///
+ /// DbContext/Repository 审计值事件,适合 Scoped IOC 中获取登陆信息
+ ///
+ public event EventHandler AuditValue;
+ public EventHandler AuditValueHandler => AuditValue;
+ }
+
+ public class DbContextAuditValueEventArgs : EventArgs
+ {
+ public DbContextAuditValueEventArgs(Aop.AuditValueType auditValueType, Type entityType, object obj)
+ {
+ this.AuditValueType = auditValueType;
+ this.EntityType = entityType;
+ this.Object = obj;
+ }
+
+ ///
+ /// 类型
+ ///
+ public Aop.AuditValueType AuditValueType { get; }
+ ///
+ /// 类型
+ ///
+ public Type EntityType { get; }
+ ///
+ /// 实体对象
+ ///
+ public object Object { get; }
}
}
diff --git a/FreeSql.DbContext/DbSet/DbSet.cs b/FreeSql.DbContext/DbSet/DbSet.cs
index aa84e759..71e54eb5 100644
--- a/FreeSql.DbContext/DbSet/DbSet.cs
+++ b/FreeSql.DbContext/DbSet/DbSet.cs
@@ -66,16 +66,27 @@ namespace FreeSql
if (_db.Options.NoneParameter != null) insert.NoneParameter(_db.Options.NoneParameter.Value);
return insert;
}
- protected virtual IInsert OrmInsert(TEntity data)
+ protected virtual IInsert OrmInsert(TEntity entity)
{
var insert = OrmInsert();
- if (data != null) (insert as InsertProvider)._source.Add(data); //防止 Aop.AuditValue 触发两次
+ if (entity != null)
+ {
+ (insert as InsertProvider)._source.Add(entity); //防止 Aop.AuditValue 触发两次
+ if (_db.Options.AuditValueHandler != null)
+ _db.Options.AuditValueHandler(_db, new DbContextAuditValueEventArgs(Aop.AuditValueType.Insert, _table.Type, entity));
+ }
return insert;
}
- protected virtual IInsert OrmInsert(IEnumerable data)
+ protected virtual IInsert OrmInsert(IEnumerable entitys)
{
var insert = OrmInsert();
- if (data != null) (insert as InsertProvider)._source.AddRange(data.Where(a => a != null)); //防止 Aop.AuditValue 触发两次
+ if (entitys != null)
+ {
+ (insert as InsertProvider)._source.AddRange(entitys.Where(a => a != null)); //防止 Aop.AuditValue 触发两次
+ if (_db.Options.AuditValueHandler != null)
+ foreach (var item in entitys)
+ _db.Options.AuditValueHandler(_db, new DbContextAuditValueEventArgs(Aop.AuditValueType.Insert, _table.Type, item));
+ }
return insert;
}
@@ -84,7 +95,13 @@ namespace FreeSql
var update = _db.OrmOriginal.Update().AsType(_entityType).WithTransaction(_uow?.GetOrBeginTransaction());
if (_db.Options.NoneParameter != null) update.NoneParameter(_db.Options.NoneParameter.Value);
if (_db.Options.EnableGlobalFilter == false) update.DisableGlobalFilter();
- if (entitys != null) (update as UpdateProvider)._source.AddRange(entitys.Where(a => a != null)); //防止 Aop.AuditValue 触发两次
+ if (entitys != null)
+ {
+ (update as UpdateProvider)._source.AddRange(entitys.Where(a => a != null)); //防止 Aop.AuditValue 触发两次
+ if (_db.Options.AuditValueHandler != null)
+ foreach (var item in entitys)
+ _db.Options.AuditValueHandler(_db, new DbContextAuditValueEventArgs(Aop.AuditValueType.Update, _table.Type, item));
+ }
return update;
}
protected virtual IDelete OrmDelete(object dywhere)
diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml
index 1567ec63..3de63092 100644
--- a/FreeSql.DbContext/FreeSql.DbContext.xml
+++ b/FreeSql.DbContext/FreeSql.DbContext.xml
@@ -130,6 +130,26 @@
实体变化事件
+
+
+ DbContext/Repository 审计值事件,适合 Scoped IOC 中获取登陆信息
+
+
+
+
+ 类型
+
+
+
+
+ 类型
+
+
+
+
+ 实体对象
+
+
动态Type,在使用 DbSet<object> 后使用本方法,指定实体类型
@@ -806,5 +826,14 @@
+
+
+ 批量注入 Repository,可以参考代码自行调整
+
+
+
+
+
+
diff --git a/FreeSql.DbContext/UnitOfWork/UnitOfWorkManager.cs b/FreeSql.DbContext/UnitOfWork/UnitOfWorkManager.cs
index 375a0e4f..dd5a16aa 100644
--- a/FreeSql.DbContext/UnitOfWork/UnitOfWorkManager.cs
+++ b/FreeSql.DbContext/UnitOfWork/UnitOfWorkManager.cs
@@ -72,6 +72,7 @@ namespace FreeSql
{
var repoInfo = new RepoInfo(repository);
repository.UnitOfWork = Current;
+ if (_repos.Any(a => a.Repository == repository)) return;
_repos.Add(repoInfo);
}
void SetAllRepositoryUow()
diff --git a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs
index 25c447f1..0a2e1296 100644
--- a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs
+++ b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs
@@ -163,6 +163,7 @@ public static partial class FreeSqlGlobalExtensions
public static object CreateInstanceGetDefaultValue(this Type that)
{
if (that == null) return null;
+ if (that == typeof(void)) return null;
if (that == typeof(string)) return default(string);
if (that == typeof(Guid)) return default(Guid);
if (that == typeof(byte[])) return default(byte[]);
diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml
index 4d006dda..8f213e5c 100644
--- a/FreeSql/FreeSql.xml
+++ b/FreeSql/FreeSql.xml
@@ -1104,6 +1104,82 @@
+
+
+ 动态创建实体类型
+
+
+
+
+ 配置Class
+
+ 类名
+ 类标记的特性[Table(Name = "xxx")] [Index(xxxx)]
+
+
+
+
+ 配置属性
+
+ 属性名称
+ 属性类型
+ 属性标记的特性-支持多个
+
+
+
+
+ 配置属性
+
+ 属性名称
+ 属性类型
+ 该属性是否重写父类属性
+ 属性标记的特性-支持多个
+
+
+
+
+ 配置属性
+
+ 属性名称
+ 属性类型
+ 该属性是否重写父类属性
+ 属性默认值
+ 属性标记的特性-支持多个
+
+
+
+
+ 配置父类
+
+ 父类类型
+
+
+
+
+ Override属性
+
+
+
+
+
+ Emit动态创建出Class - Type
+
+
+
+
+
+ 首字母小写
+
+
+
+
+
+
+ 首字母大写
+
+
+
+
获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 null
@@ -3283,6 +3359,13 @@
+
+
+ 执行SQL语句,返回更新后的记录
+ 注意:此方法只有 Postgresql/SqlServer 有效果
+
+
+
指定事务对象
@@ -3627,6 +3710,177 @@
+
+
+ 测试数据库是否连接正确,本方法执行如下命令:
+ MySql/SqlServer/PostgreSQL/达梦/人大金仓/神通: SELECT 1
+ Oracle: SELECT 1 FROM dual
+
+ 命令超时设置(秒)
+
+ true: 成功, false: 失败
+
+
+
+ 查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】
+
+
+
+
+
+
+
+
+
+ 查询,ExecuteReaderAsync(dr => {}, "select * from user where age > @age", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+
+
+ 查询,ExecuteArrayAsync("select * from user where age > @age", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+
+
+ 查询,ExecuteDataSetAsync("select * from user where age > @age; select 2", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+
+
+ 查询,ExecuteDataTableAsync("select * from user where age > @age", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+ 在【主库】执行
+
+
+
+
+
+
+
+
+ 在【主库】执行,ExecuteNonQueryAsync("delete from user where age > @age", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+ 在【主库】执行
+
+
+
+
+
+
+
+
+ 在【主库】执行,ExecuteScalarAsync("select 1 from user where age > @age", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+ 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new SqlParameter { ParameterName = "age", Value = 25 })
+
+
+
+
+
+
+
+
+
+
+ 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+
+ 执行SQL返回对象集合,Query<User>("select * from user where age > @age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 })
+
+
+
+
+
+
+
+
+
+
+
+ 执行SQL返回对象集合,Query<User, Address>("select * from user where age > @age; select * from address", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
可自定义解析表达式
@@ -4626,6 +4880,12 @@
超时
+
+
+ 获取资源
+
+
+
使用完毕后,归还资源
@@ -4701,6 +4961,12 @@
资源对象
+
+
+ 从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
+
+ 资源对象
+
归还对象给对象池的时候触发
@@ -5631,6 +5897,28 @@
请使用 fsql.InsertDict(dict) 方法插入字典数据
+
+
+ 动态构建Class Type
+
+
+
+
+
+ 根据字典,创建 table 对应的实体对象
+
+
+
+
+
+
+
+ 根据实体对象,创建 table 对应的字典
+
+
+
+
+
C#: that >= between && that <= and