diff --git a/BenchmarkTest/BenchmarkTest.csproj b/BenchmarkTest/BenchmarkTest.csproj
index a8359ae..5d22a72 100644
--- a/BenchmarkTest/BenchmarkTest.csproj
+++ b/BenchmarkTest/BenchmarkTest.csproj
@@ -2,7 +2,7 @@
Exe
- net9.0
+ net10.0
enable
diff --git a/Directory.Build.props b/Directory.Build.props
index 2299fd2..340a526 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,6 +1,6 @@
- 2025.5.4
+ 2025.6
true
\ No newline at end of file
diff --git a/Masuit.Tools.Abstractions/Masuit.Tools.Abstractions.csproj b/Masuit.Tools.Abstractions/Masuit.Tools.Abstractions.csproj
index 5b7b4dd..43a458f 100644
--- a/Masuit.Tools.Abstractions/Masuit.Tools.Abstractions.csproj
+++ b/Masuit.Tools.Abstractions/Masuit.Tools.Abstractions.csproj
@@ -1,6 +1,6 @@
- netstandard2.0;netstandard2.1;net461;net6;net8;net9
+ netstandard2.0;netstandard2.1;net461;net6;net8;net9;net10.0
latest
enable
true
@@ -47,13 +47,13 @@
-
+
-
+
-
+
@@ -61,7 +61,6 @@
-
@@ -103,21 +102,28 @@
+
+
+
+
+
+
+
-
+
-
+
-
+
diff --git a/Masuit.Tools.Abstractions/Media/ImageHasher.cs b/Masuit.Tools.Abstractions/Media/ImageHasher.cs
index 44fbc12..1cf185c 100644
--- a/Masuit.Tools.Abstractions/Media/ImageHasher.cs
+++ b/Masuit.Tools.Abstractions/Media/ImageHasher.cs
@@ -14,9 +14,6 @@ namespace Masuit.Tools.Media;
public class ImageHasher
{
private readonly IImageTransformer _transformer;
- private float[][] _dctMatrix;
- private bool _isDctMatrixInitialized;
- private readonly object _dctMatrixLockObject = new();
///
/// 默认使用ImageSharpTransformer初始化实例
diff --git a/Masuit.Tools.Abstractions/Security/RsaPem.cs b/Masuit.Tools.Abstractions/Security/RsaPem.cs
index 8ac4e88..9374e80 100644
--- a/Masuit.Tools.Abstractions/Security/RsaPem.cs
+++ b/Masuit.Tools.Abstractions/Security/RsaPem.cs
@@ -184,8 +184,8 @@ internal class RsaPem
Array.Copy(bigb, 0, c, 1, bigb.Length);
bigb = c;
}
-
- return new BigInteger(bigb.Reverse().ToArray()); //C#的二进制是反的
+ bigb.Reverse();
+ return new BigInteger(bigb);
}
///
@@ -193,15 +193,16 @@ internal class RsaPem
///
public static byte[] BigB(BigInteger bigx)
{
- byte[] val = bigx.ToByteArray().Reverse().ToArray(); //C#的二进制是反的
- if (val[0] == 0)
+ var bytes = bigx.ToByteArray();
+ bytes.Reverse();
+ if (bytes[0] == 0)
{
- byte[] c = new byte[val.Length - 1];
- Array.Copy(val, 1, c, 0, c.Length);
- val = c;
+ byte[] c = new byte[bytes.Length - 1];
+ Array.Copy(bytes, 1, c, 0, c.Length);
+ bytes = c;
}
- return val;
+ return bytes;
}
///
@@ -690,4 +691,4 @@ internal class RsaPem
str.Append("");
return str.ToString();
}
-}
+}
\ No newline at end of file
diff --git a/Masuit.Tools.AspNetCore/Masuit.Tools.AspNetCore.csproj b/Masuit.Tools.AspNetCore/Masuit.Tools.AspNetCore.csproj
index 98d3855..7242ca8 100644
--- a/Masuit.Tools.AspNetCore/Masuit.Tools.AspNetCore.csproj
+++ b/Masuit.Tools.AspNetCore/Masuit.Tools.AspNetCore.csproj
@@ -1,7 +1,7 @@
- netcoreapp3.1;net6;net8;net9
+ netcoreapp3.1;net6;net8;net9;net10.0
enable
全龄段友好的C#万能工具库,码数吐司库(适用于.NET Core Web项目),不管你是菜鸟新手还是骨灰级玩家都能轻松上手,包含一些常用的操作类,大都是静态类,加密解密,反射操作,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。包含一些AspNetCore常用的工具类、ModelBinder等。
@@ -57,6 +57,9 @@
+
+
+
diff --git a/Masuit.Tools.Core/Database/DbContextExt.cs b/Masuit.Tools.Core/Database/DbContextExt.cs
index 018696a..a6206c4 100644
--- a/Masuit.Tools.Core/Database/DbContextExt.cs
+++ b/Masuit.Tools.Core/Database/DbContextExt.cs
@@ -12,562 +12,586 @@ namespace Masuit.Tools.Core;
public static class DbContextExt
{
- ///
- /// 获取变化的实体信息
- ///
- ///
- ///
- ///
- public static IEnumerable> GetChanges(this DbContext db)
- {
- return db.ChangeTracker.Entries().Where(e => e is { State: EntityState.Modified, Entity: T }).Select(e =>
- {
- NullableDictionary originalObject = e.OriginalValues.ToObject() as Dictionary ?? new NullableDictionary();
- NullableDictionary currentObject = e.CurrentValues.ToObject() as Dictionary ?? new NullableDictionary();
- return new ChangeEntry
- {
- EntityState = e.State,
- Entity = (T)e.Entity,
- EntityType = e.OriginalValues.EntityType.ClrType,
- ChangeProperties = e.OriginalValues.Properties.Select(p => (Property: p, Value: originalObject[p.PropertyInfo?.Name])).Zip(e.CurrentValues.Properties.Select(p => (Property: p, Value: currentObject[p.PropertyInfo?.Name])), (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 =>
- {
- NullableDictionary originalObject = e.OriginalValues.ToObject() as Dictionary ?? new NullableDictionary();
- NullableDictionary currentObject = e.CurrentValues.ToObject() as Dictionary ?? new NullableDictionary();
- return new ChangeEntry
- {
- EntityState = e.State,
- Entity = e.Entity,
- EntityType = e.OriginalValues.EntityType.ClrType,
- ChangeProperties = e.OriginalValues.Properties.Select(p => (Property: p, Value: originalObject[p.PropertyInfo?.Name])).Zip(e.CurrentValues.Properties.Select(p => (Property: p, Value: currentObject[p.PropertyInfo?.Name])), (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 =>
- {
- NullableDictionary currentObject = e.CurrentValues.ToObject() as Dictionary ?? new NullableDictionary();
- return new ChangeEntry
- {
- EntityState = e.State,
- Entity = (T)e.Entity,
- EntityType = e.CurrentValues.EntityType.ClrType,
- ChangeProperties = e.CurrentValues.Properties.Select(p => new ChangePropertyInfo()
- {
- PropertyInfo = p.PropertyInfo,
- CurrentValue = currentObject[p.PropertyInfo?.Name],
- 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 =>
- {
- NullableDictionary currentObject = e.CurrentValues.ToObject() as Dictionary ?? new NullableDictionary();
- 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 = currentObject[p.PropertyInfo?.Name],
- 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 =>
- {
- NullableDictionary originalObject = e.OriginalValues.ToObject() as Dictionary ?? new NullableDictionary();
- return new ChangeEntry
- {
- EntityState = e.State,
- Entity = (T)e.Entity,
- EntityType = e.OriginalValues.EntityType.ClrType,
- ChangeProperties = e.OriginalValues.Properties.Select(p => new ChangePropertyInfo
- {
- PropertyInfo = p.PropertyInfo,
- OriginalValue = originalObject[p.PropertyInfo?.Name],
- 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 =>
- {
- NullableDictionary originalObject = e.OriginalValues.ToObject() as Dictionary ?? new NullableDictionary();
- 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 = originalObject[p.PropertyInfo?.Name],
- 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 static IQueryable IncludeRecursive(this IQueryable source, int levelIndex, Expression>> expression) where TEntity : class
- {
- if (levelIndex < 0)
- throw new ArgumentOutOfRangeException(nameof(levelIndex));
- var member = (MemberExpression)expression.Body;
- var property = member.Member.Name;
- var sb = new StringBuilder();
- for (int i = 0; i < levelIndex; i++)
- {
- if (i > 0)
- sb.Append(Type.Delimiter);
- sb.Append(property);
- }
-
- return source.Include(sb.ToString());
- }
-
- public static Task> ToListWithNoLockAsync(this IQueryable query, CancellationToken cancellationToken = default)
- {
- return ExecuteStrategyAsync(query, async (q) =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = await q.ToListAsync(cancellationToken);
- scope.Complete();
- return result;
- });
- }
-
- public static List ToListWithNoLock(this IQueryable query)
- {
- return ExecuteStrategy(query, q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = q.ToList();
- scope.Complete();
- return result;
- });
- }
-
- public static Task CountWithNoLockAsync(this IQueryable query, CancellationToken cancellationToken = default)
- {
- return ExecuteStrategyAsync(query, async q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = await q.CountAsync(cancellationToken);
- scope.Complete();
- return result;
- });
- }
-
- public static int CountWithNoLock(this IQueryable query)
- {
- return ExecuteStrategy(query, q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = q.Count();
- scope.Complete();
- return result;
- });
- }
-
- public static Task CountWithNoLockAsync(this IQueryable query, Expression> where, CancellationToken cancellationToken = default)
- {
- return ExecuteStrategyAsync(query, async q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = await q.CountAsync(where, cancellationToken);
- scope.Complete();
- return result;
- });
- }
-
- public static int CountWithNoLock(this IQueryable query, Expression> where)
- {
- return ExecuteStrategy(query, q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = q.Count(where);
- scope.Complete();
- return result;
- });
- }
-
- public static Task AnyWithNoLockAsync(this IQueryable query, CancellationToken cancellationToken = default)
- {
- return ExecuteStrategyAsync(query, async q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = await q.AnyAsync(cancellationToken);
- scope.Complete();
- return result;
- });
- }
-
- public static bool AnyWithNoLock(this IQueryable query)
- {
- return ExecuteStrategy(query, q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = q.Any();
- scope.Complete();
- return result;
- });
- }
-
- public static Task AnyWithNoLockAsync(this IQueryable query, Expression> where, CancellationToken cancellationToken = default)
- {
- return ExecuteStrategyAsync(query, async q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = await q.AnyAsync(where, cancellationToken);
- scope.Complete();
- return result;
- });
- }
-
- public static bool AnyWithNoLock(this IQueryable query, Expression> where)
- {
- return ExecuteStrategy(query, q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = q.Any(where);
- scope.Complete();
- return result;
- });
- }
-
- public static Task FirstOrDefaultWithNoLockAsync(this IQueryable query, Expression> where, CancellationToken cancellationToken = default)
- {
- return ExecuteStrategyAsync(query, async q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = await q.FirstOrDefaultAsync(where, cancellationToken);
- scope.Complete();
- return result;
- });
- }
-
- public static T FirstOrDefaultWithNoLock(this IQueryable query, Expression> where)
- {
- return ExecuteStrategy(query, q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = q.FirstOrDefault(where);
- scope.Complete();
- return result;
- });
- }
-
- public static Task FirstOrDefaultWithNoLockAsync(this IQueryable query, CancellationToken cancellationToken = default)
- {
- return ExecuteStrategyAsync(query, async q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = await q.FirstOrDefaultAsync(cancellationToken);
- scope.Complete();
- return result;
- });
- }
-
- public static T FirstOrDefaultWithNoLock(this IQueryable query)
- {
- return ExecuteStrategy(query, q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = q.FirstOrDefault();
- scope.Complete();
- return result;
- });
- }
-
- public static Task SingleOrDefaultWithNoLockAsync(this IQueryable query, Expression> where, CancellationToken cancellationToken = default)
- {
- return ExecuteStrategyAsync(query, async q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = await q.SingleOrDefaultAsync(where, cancellationToken);
- scope.Complete();
- return result;
- });
- }
-
- public static T SingleOrDefaultWithNoLock(this IQueryable query, Expression> where)
- {
- return ExecuteStrategy(query, q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = q.SingleOrDefault(where);
- scope.Complete();
- return result;
- });
- }
-
- public static Task SingleOrDefaultWithNoLockAsync(this IQueryable query, CancellationToken cancellationToken = default)
- {
- return ExecuteStrategyAsync(query, async q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = await q.SingleOrDefaultAsync(cancellationToken);
- scope.Complete();
- return result;
- });
- }
-
- public static T SingleOrDefaultWithNoLock(this IQueryable query)
- {
- return ExecuteStrategy(query, q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = q.SingleOrDefault();
- scope.Complete();
- return result;
- });
- }
-
- public static Task AllWithNoLockAsync(this IQueryable query, Expression> where, CancellationToken cancellationToken = default)
- {
- return ExecuteStrategyAsync(query, async q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = await q.AllAsync(where, cancellationToken);
- scope.Complete();
- return result;
- });
- }
-
- public static bool AllWithNoLock(this IQueryable query, Expression> where)
- {
- return ExecuteStrategy(query, q =>
- {
- using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- }, TransactionScopeAsyncFlowOption.Enabled);
- var result = query.All(where);
- scope.Complete();
- return result;
- });
- }
-
- public static T NoLock(this TDbContext dbContext, Func func) where TDbContext : DbContext
- {
- var strategy = dbContext.Database.CreateExecutionStrategy();
- return strategy.Execute(() =>
- {
- var transactionOptions = new TransactionOptions
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- };
- using var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions);
- var result = func(dbContext);
- scope.Complete();
- return result;
- });
- }
-
- public static Task NoLock(this TDbContext dbContext, Func> func) where TDbContext : DbContext
- {
- var strategy = dbContext.Database.CreateExecutionStrategy();
- return strategy.ExecuteAsync(async () =>
- {
- var transactionOptions = new TransactionOptions
- {
- IsolationLevel = IsolationLevel.ReadUncommitted
- };
- using var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions);
- var result = await func(dbContext);
- scope.Complete();
- return result;
- });
- }
-
- public static T ExecuteStrategy(this TDbContext dbContext, Func func) where TDbContext : DbContext
- {
- var strategy = dbContext.Database.CreateExecutionStrategy();
- return strategy.Execute(() => func(dbContext));
- }
-
- public static Task ExecuteStrategy(this TDbContext dbContext, Func> func) where TDbContext : DbContext
- {
- var strategy = dbContext.Database.CreateExecutionStrategy();
- return strategy.ExecuteAsync(() => func(dbContext));
- }
-
- public static TResult ExecuteStrategy(this IQueryable query, Func, TResult> func)
- {
- if (query.Provider is not EntityQueryProvider)
- {
- return func(query);
- }
-
- var dependencies = query.Provider.GetField("_queryCompiler").GetField("_compiledQueryCacheKeyGenerator").GetField("Dependencies");
-#if NETSTANDARD2_0
- var context = dependencies.Context.Context;
+ ///
+ /// 获取变化的实体信息
+ ///
+ ///
+ ///
+ ///
+ public static IEnumerable> GetChanges(this DbContext db)
+ {
+ return db.ChangeTracker.Entries().Where(e => e is { State: EntityState.Modified, Entity: T }).Select(e =>
+ {
+ NullableDictionary originalObject = e.OriginalValues.ToObject() as Dictionary ?? new NullableDictionary();
+ NullableDictionary currentObject = e.CurrentValues.ToObject() as Dictionary ?? new NullableDictionary();
+ return new ChangeEntry
+ {
+ EntityState = e.State,
+ Entity = (T)e.Entity,
+#if NET10_0_OR_GREATER
+ EntityType = e.OriginalValues.StructuralType.ClrType,
#else
- var context = dependencies.CurrentContext.Context;
+ EntityType = e.OriginalValues.EntityType.ClrType,
#endif
- var strategy = context.Database.CreateExecutionStrategy();
- return strategy.Execute(() => func(query));
- }
+ ChangeProperties = e.OriginalValues.Properties.Select(p => (Property: p, Value: originalObject[p.PropertyInfo?.Name])).Zip(e.CurrentValues.Properties.Select(p => (Property: p, Value: currentObject[p.PropertyInfo?.Name])), (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 Task ExecuteStrategyAsync(this IQueryable query, Func, Task> func)
- {
- if (query.Provider is not EntityQueryProvider)
- {
- return func(query);
- }
-
- var dependencies = query.Provider.GetField("_queryCompiler").GetField("_compiledQueryCacheKeyGenerator").GetField("Dependencies");
-#if NETSTANDARD2_0
- var context = dependencies.Context.Context;
+ ///
+ /// 获取变化的实体信息
+ ///
+ ///
+ ///
+ public static IEnumerable GetChanges(this DbContext db)
+ {
+ return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified).Select(e =>
+ {
+ NullableDictionary originalObject = e.OriginalValues.ToObject() as Dictionary ?? new NullableDictionary();
+ NullableDictionary currentObject = e.CurrentValues.ToObject() as Dictionary ?? new NullableDictionary();
+ return new ChangeEntry
+ {
+ EntityState = e.State,
+ Entity = e.Entity,
+#if NET10_0_OR_GREATER
+ EntityType = e.OriginalValues.StructuralType.ClrType,
#else
- var context = dependencies.CurrentContext.Context;
+ EntityType = e.OriginalValues.EntityType.ClrType,
#endif
- var strategy = context.Database.CreateExecutionStrategy();
- return strategy.ExecuteAsync(() => func(query));
- }
+ ChangeProperties = e.OriginalValues.Properties.Select(p => (Property: p, Value: originalObject[p.PropertyInfo?.Name])).Zip(e.CurrentValues.Properties.Select(p => (Property: p, Value: currentObject[p.PropertyInfo?.Name])), (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 =>
+ {
+ NullableDictionary currentObject = e.CurrentValues.ToObject() as Dictionary ?? new NullableDictionary();
+ return new ChangeEntry
+ {
+ EntityState = e.State,
+ Entity = (T)e.Entity,
+#if NET10_0_OR_GREATER
+ EntityType = e.OriginalValues.StructuralType.ClrType,
+#else
+ EntityType = e.OriginalValues.EntityType.ClrType,
+#endif
+ ChangeProperties = e.CurrentValues.Properties.Select(p => new ChangePropertyInfo()
+ {
+ PropertyInfo = p.PropertyInfo,
+ CurrentValue = currentObject[p.PropertyInfo?.Name],
+ 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 =>
+ {
+ NullableDictionary currentObject = e.CurrentValues.ToObject() as Dictionary ?? new NullableDictionary();
+ return new ChangeEntry
+ {
+ EntityState = e.State,
+ Entity = e.Entity,
+#if NET10_0_OR_GREATER
+ EntityType = e.OriginalValues.StructuralType.ClrType,
+#else
+ EntityType = e.OriginalValues.EntityType.ClrType,
+#endif
+ ChangeProperties = e.CurrentValues.Properties.Select(p => new ChangePropertyInfo
+ {
+ PropertyInfo = p.PropertyInfo,
+ CurrentValue = currentObject[p.PropertyInfo?.Name],
+ 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 =>
+ {
+ NullableDictionary originalObject = e.OriginalValues.ToObject() as Dictionary ?? new NullableDictionary();
+ return new ChangeEntry
+ {
+ EntityState = e.State,
+ Entity = (T)e.Entity,
+#if NET10_0_OR_GREATER
+ EntityType = e.OriginalValues.StructuralType.ClrType,
+#else
+ EntityType = e.OriginalValues.EntityType.ClrType,
+#endif
+ ChangeProperties = e.OriginalValues.Properties.Select(p => new ChangePropertyInfo
+ {
+ PropertyInfo = p.PropertyInfo,
+ OriginalValue = originalObject[p.PropertyInfo?.Name],
+ 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 =>
+ {
+ NullableDictionary originalObject = e.OriginalValues.ToObject() as Dictionary ?? new NullableDictionary();
+ return new ChangeEntry
+ {
+ EntityState = e.State,
+ Entity = e.Entity,
+#if NET10_0_OR_GREATER
+ EntityType = e.OriginalValues.StructuralType.ClrType,
+#else
+ EntityType = e.OriginalValues.EntityType.ClrType,
+#endif
+ ChangeProperties = e.OriginalValues.Properties.Select(p => new ChangePropertyInfo
+ {
+ PropertyInfo = p.PropertyInfo,
+ OriginalValue = originalObject[p.PropertyInfo?.Name],
+ 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 static IQueryable IncludeRecursive(this IQueryable source, int levelIndex, Expression>> expression) where TEntity : class
+ {
+ if (levelIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(levelIndex));
+ var member = (MemberExpression)expression.Body;
+ var property = member.Member.Name;
+ var sb = new StringBuilder();
+ for (int i = 0; i < levelIndex; i++)
+ {
+ if (i > 0)
+ sb.Append(Type.Delimiter);
+ sb.Append(property);
+ }
+
+ return source.Include(sb.ToString());
+ }
+
+ public static Task> ToListWithNoLockAsync(this IQueryable query, CancellationToken cancellationToken = default)
+ {
+ return ExecuteStrategyAsync(query, async (q) =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = await q.ToListAsync(cancellationToken);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static List ToListWithNoLock(this IQueryable query)
+ {
+ return ExecuteStrategy(query, q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = q.ToList();
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static Task CountWithNoLockAsync(this IQueryable query, CancellationToken cancellationToken = default)
+ {
+ return ExecuteStrategyAsync(query, async q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = await q.CountAsync(cancellationToken);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static int CountWithNoLock(this IQueryable query)
+ {
+ return ExecuteStrategy(query, q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = q.Count();
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static Task CountWithNoLockAsync(this IQueryable query, Expression> where, CancellationToken cancellationToken = default)
+ {
+ return ExecuteStrategyAsync(query, async q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = await q.CountAsync(where, cancellationToken);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static int CountWithNoLock(this IQueryable query, Expression> where)
+ {
+ return ExecuteStrategy(query, q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = q.Count(where);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static Task AnyWithNoLockAsync(this IQueryable query, CancellationToken cancellationToken = default)
+ {
+ return ExecuteStrategyAsync(query, async q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = await q.AnyAsync(cancellationToken);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static bool AnyWithNoLock(this IQueryable query)
+ {
+ return ExecuteStrategy(query, q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = q.Any();
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static Task AnyWithNoLockAsync(this IQueryable query, Expression> where, CancellationToken cancellationToken = default)
+ {
+ return ExecuteStrategyAsync(query, async q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = await q.AnyAsync(where, cancellationToken);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static bool AnyWithNoLock(this IQueryable query, Expression> where)
+ {
+ return ExecuteStrategy(query, q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = q.Any(where);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static Task FirstOrDefaultWithNoLockAsync(this IQueryable query, Expression> where, CancellationToken cancellationToken = default)
+ {
+ return ExecuteStrategyAsync(query, async q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = await q.FirstOrDefaultAsync(where, cancellationToken);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static T FirstOrDefaultWithNoLock(this IQueryable query, Expression> where)
+ {
+ return ExecuteStrategy(query, q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = q.FirstOrDefault(where);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static Task FirstOrDefaultWithNoLockAsync(this IQueryable query, CancellationToken cancellationToken = default)
+ {
+ return ExecuteStrategyAsync(query, async q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = await q.FirstOrDefaultAsync(cancellationToken);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static T FirstOrDefaultWithNoLock(this IQueryable query)
+ {
+ return ExecuteStrategy(query, q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = q.FirstOrDefault();
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static Task SingleOrDefaultWithNoLockAsync(this IQueryable query, Expression> where, CancellationToken cancellationToken = default)
+ {
+ return ExecuteStrategyAsync(query, async q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = await q.SingleOrDefaultAsync(where, cancellationToken);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static T SingleOrDefaultWithNoLock(this IQueryable query, Expression> where)
+ {
+ return ExecuteStrategy(query, q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = q.SingleOrDefault(where);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static Task SingleOrDefaultWithNoLockAsync(this IQueryable query, CancellationToken cancellationToken = default)
+ {
+ return ExecuteStrategyAsync(query, async q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = await q.SingleOrDefaultAsync(cancellationToken);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static T SingleOrDefaultWithNoLock(this IQueryable query)
+ {
+ return ExecuteStrategy(query, q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = q.SingleOrDefault();
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static Task AllWithNoLockAsync(this IQueryable query, Expression> where, CancellationToken cancellationToken = default)
+ {
+ return ExecuteStrategyAsync(query, async q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = await q.AllAsync(where, cancellationToken);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static bool AllWithNoLock(this IQueryable query, Expression> where)
+ {
+ return ExecuteStrategy(query, q =>
+ {
+ using var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ }, TransactionScopeAsyncFlowOption.Enabled);
+ var result = query.All(where);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static T NoLock(this TDbContext dbContext, Func func) where TDbContext : DbContext
+ {
+ var strategy = dbContext.Database.CreateExecutionStrategy();
+ return strategy.Execute(() =>
+ {
+ var transactionOptions = new TransactionOptions
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ };
+ using var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions);
+ var result = func(dbContext);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static Task NoLock(this TDbContext dbContext, Func> func) where TDbContext : DbContext
+ {
+ var strategy = dbContext.Database.CreateExecutionStrategy();
+ return strategy.ExecuteAsync(async () =>
+ {
+ var transactionOptions = new TransactionOptions
+ {
+ IsolationLevel = IsolationLevel.ReadUncommitted
+ };
+ using var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions);
+ var result = await func(dbContext);
+ scope.Complete();
+ return result;
+ });
+ }
+
+ public static T ExecuteStrategy(this TDbContext dbContext, Func func) where TDbContext : DbContext
+ {
+ var strategy = dbContext.Database.CreateExecutionStrategy();
+ return strategy.Execute(() => func(dbContext));
+ }
+
+ public static Task ExecuteStrategy