修改仓储批量更新和批量删除方法
This commit is contained in:
@@ -37,8 +37,6 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
optionsBuilder.UseLoggerFactory(MyLoggerFactory)
|
||||
.ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactoryDesignTimeSupport>();
|
||||
|
||||
optionsBuilder.UseBatchEF_MSSQL();
|
||||
|
||||
//var config = new ConfigurationBuilder()
|
||||
// .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true).Build();
|
||||
//connectionString = config.GetSection("ConnectionStrings:RemoteNew").Value;
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="6.0.0" />
|
||||
<PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="6.13.6" />
|
||||
<PackageReference Include="Zack.EFCore.Batch.MSSQL_NET6" Version="6.0.12" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -23,10 +23,8 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
Task<TEntity> UpdatePartialFields(Guid id, Expression<Func<TEntity, TEntity>> updateFactory, bool autoSave = false, params EntityVerifyExp<TEntity>[] verify);
|
||||
|
||||
|
||||
Task<bool> BatchUpdateAsync(Expression<Func<TEntity, bool>> where,
|
||||
Expression<Func<TEntity, TEntity>> updateFactory);
|
||||
|
||||
Task<bool> BatchDeleteAsync(Expression<Func<TEntity, bool>> deleteFilter);
|
||||
Task<bool> BatchUpdateAsync(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TEntity>> updateFactory);
|
||||
|
||||
}
|
||||
|
||||
@@ -56,8 +54,7 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
Task<bool> DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);
|
||||
Task<bool> DeleteManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default);
|
||||
|
||||
Task<bool> DeleteFromQueryAsync(Expression<Func<TEntity, bool>> deleteFilter) ;
|
||||
Task<bool> UpdateFromQueryAsync(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TEntity>> updateFactory);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using EFCore.BulkExtensions;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
|
||||
namespace IRaCIS.Core.Infra.EFCore
|
||||
{
|
||||
@@ -59,9 +61,9 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
|
||||
Task<bool> SaveChangesAsync();
|
||||
|
||||
Task<bool> DeleteFromQueryAsync<T>(Expression<Func<T, bool>> deleteFilter) where T : Entity;
|
||||
Task<bool> BatchDeleteAsync<T>(Expression<Func<T, bool>> deleteFilter) where T : Entity;
|
||||
|
||||
Task<bool> UpdateFromQueryAsync<T>(Expression<Func<T, bool>> where, Expression<Func<T, T>> updateFactory) where T : Entity;
|
||||
Task<bool> BatchUpdateAsync<T>(Expression<Func<T, bool>> where, Expression<Func<T, T>> updateFactory) where T : Entity;
|
||||
}
|
||||
|
||||
public class Repository : IRepository
|
||||
@@ -70,10 +72,13 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
|
||||
public IMapper _mapper { get; set; }
|
||||
|
||||
public Repository(IRaCISDBContext dbContext, IMapper mapper)
|
||||
public IUserInfo _userInfo { get; set; }
|
||||
|
||||
public Repository(IRaCISDBContext dbContext, IMapper mapper, IUserInfo userInfo)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_mapper = mapper;
|
||||
_userInfo = userInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -396,18 +401,32 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
|
||||
#endregion
|
||||
|
||||
public async Task<bool> DeleteFromQueryAsync<T>(Expression<Func<T, bool>> deleteFilter) where T : Entity
|
||||
public async Task<bool> BatchDeleteAsync<T>(Expression<Func<T, bool>> deleteFilter) where T : Entity
|
||||
{
|
||||
if (deleteFilter == null) throw new ArgumentNullException(nameof(deleteFilter));
|
||||
|
||||
return await _dbContext.Set<T>().AsNoTracking().Where(deleteFilter).DeleteFromQueryAsync().ConfigureAwait(false) > 0;
|
||||
return await _dbContext.Set<T>().AsNoTracking().Where(deleteFilter).BatchDeleteAsync().ConfigureAwait(false) > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateFromQueryAsync<T>(Expression<Func<T, bool>> whereFilter, Expression<Func<T, T>> updateFactory) where T : Entity
|
||||
public async Task<bool> BatchUpdateAsync<T>(Expression<Func<T, bool>> whereFilter, Expression<Func<T, T>> updateFactory) where T : Entity
|
||||
{
|
||||
if (whereFilter == null) throw new ArgumentNullException(nameof(whereFilter));
|
||||
|
||||
return await _dbContext.Set<T>().AsNoTracking().IgnoreQueryFilters().Where(whereFilter).UpdateFromQueryAsync(updateFactory).ConfigureAwait(false) > 0;
|
||||
var bindings = ((MemberInitExpression)updateFactory.Body).Bindings.ToList();
|
||||
|
||||
if (typeof(IAuditUpdate).IsAssignableFrom(typeof(T)))
|
||||
{
|
||||
|
||||
bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateTime))[0], Expression.Constant(DateTime.Now)));
|
||||
bindings.Add(Expression.Bind(typeof(TR).GetMember(nameof(IAuditUpdate.UpdateUserId))[0], Expression.Constant(_userInfo.Id)));
|
||||
}
|
||||
|
||||
|
||||
var member = Expression.MemberInit(Expression.New(typeof(T)), bindings);
|
||||
|
||||
var factory = Expression.Lambda<Func<T, T>>(member, Expression.Parameter(typeof(T), "x"));
|
||||
|
||||
return await _dbContext.Set<T>().AsNoTracking().IgnoreQueryFilters().Where(whereFilter).BatchUpdateAsync(updateFactory).ConfigureAwait(false) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using AutoMapper.QueryableExtensions;
|
||||
using EFCore.BulkExtensions;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.Data.SqlClient;
|
||||
@@ -28,11 +29,13 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
|
||||
public DbSet<TEntity> _dbSet => _dbContext.Set<TEntity>();
|
||||
|
||||
public IUserInfo _userInfo { get; set; }
|
||||
|
||||
public Repository(IRaCISDBContext dbContext, IMapper mapper)
|
||||
public Repository(IRaCISDBContext dbContext, IMapper mapper,IUserInfo userInfo)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_mapper = mapper;
|
||||
_userInfo = userInfo;
|
||||
}
|
||||
|
||||
#region 异步部分
|
||||
@@ -155,6 +158,16 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 用前端传递的视图模型字段,更新,同时返回数据库该条记录的原始信息,方便对比某些字段是否更改,进行相应的逻辑操作
|
||||
/// </summary>
|
||||
/// <typeparam name="TFrom"></typeparam>
|
||||
/// <param name="from"></param>
|
||||
/// <param name="autoSave"></param>
|
||||
/// <param name="ignoreDtoNullProperty"></param>
|
||||
/// <param name="verify"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||
public async Task<TEntity> UpdateFromDTOAsync<TFrom>(TFrom from, bool autoSave = false, bool ignoreDtoNullProperty = true, params EntityVerifyExp<TEntity>[] verify)
|
||||
{
|
||||
|
||||
@@ -180,9 +193,10 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
// Guid?属性 为null 时 映射到 Guid 时 默认会变成 Guid.Empty
|
||||
if (ignoreDtoNullProperty)
|
||||
{
|
||||
var dbEntityProp = typeof(TEntity).GetProperties();
|
||||
foreach (var propertyInfo in from.GetType().GetProperties())
|
||||
{
|
||||
if (propertyInfo.GetValue(from) == null)
|
||||
if (propertyInfo.GetValue(from) == null && dbEntityProp.Any(t=>t.Name== propertyInfo.Name))
|
||||
{
|
||||
_dbContext.Entry(dbEntity).Property(propertyInfo.Name).IsModified = false;
|
||||
}
|
||||
@@ -196,46 +210,6 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 通过主键id 和表达式树 更新部分字段 例如 Guid.Parse("8a90c96e-0776-4f7b-82a6-18933d339584"),u => new Dictionary() { ParentId = null, Code = "test" } 默认会去处理更新更新人 更新时间
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="updateFactory"></param>
|
||||
/// <param name="autoSave"></param>
|
||||
/// <param name="verify"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<TEntity> UpdatePartialFields(Guid id, Expression<Func<TEntity, TEntity>> updateFactory, bool autoSave = false, params EntityVerifyExp<TEntity>[] verify)
|
||||
{
|
||||
await EntityVerifyAsync(false, verify, id);
|
||||
|
||||
var entity = new TEntity() { Id = id };
|
||||
|
||||
var entityEntry = _dbContext.Entry(entity);
|
||||
entityEntry.State = EntityState.Detached;
|
||||
|
||||
|
||||
Func<TEntity, TEntity> func = updateFactory.Compile();
|
||||
|
||||
List<PropertyInfo> list = ((MemberInitExpression)updateFactory.Body).Bindings.Select<MemberBinding, string>((Func<MemberBinding, string>)(_param1 => _param1.Member.Name)).Select<string, PropertyInfo>((Func<string, PropertyInfo>)(_param1 => (PropertyInfo)typeof(TEntity).GetProperty(_param1, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))).ToList<PropertyInfo>();
|
||||
|
||||
|
||||
TEntity applyObj = func(entity);
|
||||
|
||||
foreach (PropertyInfo prop in list)
|
||||
{
|
||||
object value = prop.GetValue((object)applyObj);
|
||||
prop.SetValue((object)entity, value);
|
||||
|
||||
_dbContext.Entry(entity).Property(prop.Name).IsModified = true;
|
||||
}
|
||||
|
||||
|
||||
await SaveChangesAsync(autoSave);
|
||||
|
||||
return entityEntry.Entity;
|
||||
}
|
||||
|
||||
|
||||
private async Task<bool> SaveChangesAsync(bool autoSave)
|
||||
{
|
||||
if (autoSave)
|
||||
@@ -248,8 +222,65 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过主键id 和表达式树 更新部分字段 例如 Guid.Parse("8a90c96e-0776-4f7b-82a6-18933d339584"),u => new Dictionary() { ParentId = null, Code = "test" } 默认会去处理更新更新人 更新时间
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="updateFactory"></param>
|
||||
/// <param name="autoSave"></param>
|
||||
/// <param name="verify"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<TEntity> UpdatePartialFields(Guid id, Expression<Func<TEntity, TEntity>> updateFactory, bool autoSave = false, params EntityVerifyExp<TEntity>[] verify)
|
||||
{
|
||||
await EntityVerifyAsync(false, verify, id);
|
||||
|
||||
var entity = new TEntity() { Id = id };
|
||||
|
||||
var entityEntry = _dbContext.Entry(entity);
|
||||
|
||||
entityEntry.State = EntityState.Detached;
|
||||
|
||||
|
||||
List<PropertyInfo> list = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name)
|
||||
.Select(propName => typeof(TEntity).GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)).ToList();
|
||||
|
||||
Func<TEntity, TEntity> func = updateFactory.Compile();
|
||||
|
||||
TEntity applyObj = func(entity);
|
||||
|
||||
foreach (PropertyInfo prop in list)
|
||||
{
|
||||
object value = prop.GetValue((object)applyObj);
|
||||
prop.SetValue((object)entity, value);
|
||||
|
||||
_dbContext.Entry(entity).Property(prop.Name).IsModified = true;
|
||||
}
|
||||
|
||||
|
||||
await SaveChangesAsync(autoSave);
|
||||
|
||||
return entityEntry.Entity;
|
||||
|
||||
#region Test
|
||||
|
||||
|
||||
//updateFactory.Compile()(entity);
|
||||
|
||||
//List<string> propNameList = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name).ToList();
|
||||
|
||||
//foreach (string propName in propNameList)
|
||||
//{
|
||||
// _dbContext.Entry(entity).Property(propName).IsModified = true;
|
||||
//}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 部分字段更新 (只更新传递的字段名 new[] {nameof(User.Name), nameof(User.Age))
|
||||
/// new Dictionary() { ParentId = null, Code = "test",Id=Guid.Parse("8a90c96e-0776-4f7b-82a6-18933d339584")},new[] {nameof(Dictionary.Name), nameof(Dictionary.Age))
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="propertyNames"> 更新的字段数组 </param>
|
||||
@@ -501,16 +532,6 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
return whereLambda == null ? await query.AsNoTracking().CountAsync() : await query.AsNoTracking().CountAsync(whereLambda);
|
||||
}
|
||||
|
||||
// Z.EntityFramework.Plus.EFCore
|
||||
public async Task<bool> DeleteFromQueryAsync(Expression<Func<TEntity, bool>> deleteFilter)
|
||||
{
|
||||
return await _dbSet.IgnoreQueryFilters().Where(deleteFilter).DeleteFromQueryAsync() > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateFromQueryAsync(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TEntity>> updateFactory)
|
||||
{
|
||||
return await _dbSet.IgnoreQueryFilters().Where(where).UpdateFromQueryAsync(updateFactory) > 0;
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> BatchDeleteAsync(Expression<Func<TEntity, bool>> deleteFilter)
|
||||
@@ -523,7 +544,27 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
Expression<Func<TEntity, TEntity>> updateFactory)
|
||||
{
|
||||
|
||||
return await _dbSet.IgnoreQueryFilters().Where(where).BatchUpdateAsync(updateFactory) > 0;
|
||||
//return await _dbSet.IgnoreQueryFilters().Where(where).BatchUpdateAsync(updateFactory) > 0;
|
||||
|
||||
var bindings = ((MemberInitExpression)updateFactory.Body).Bindings.ToList();
|
||||
|
||||
if (typeof(IAuditUpdate).IsAssignableFrom(typeof(TEntity)))
|
||||
{
|
||||
|
||||
bindings.Add(Expression.Bind(typeof(TEntity).GetMember(nameof(IAuditUpdate.UpdateTime))[0], Expression.Constant(DateTime.Now)));
|
||||
bindings.Add(Expression.Bind(typeof(TEntity).GetMember(nameof(IAuditUpdate.UpdateUserId))[0], Expression.Constant(_userInfo.Id)));
|
||||
}
|
||||
|
||||
|
||||
var member = Expression.MemberInit(Expression.New(typeof(TEntity)), bindings);
|
||||
|
||||
var factory = Expression.Lambda<Func<TEntity, TEntity>>(member, Expression.Parameter(typeof(TEntity), "x"));
|
||||
|
||||
|
||||
return await _dbSet.IgnoreQueryFilters().Where(where).BatchUpdateAsync(factory) > 0;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -570,6 +611,16 @@ namespace IRaCIS.Core.Infra.EFCore
|
||||
// return await builder.Where(where).ExecuteAsync()>0;
|
||||
//}
|
||||
|
||||
//// Z.EntityFramework.Plus.EFCore
|
||||
//public async Task<bool> BatchDeleteAsync(Expression<Func<TEntity, bool>> deleteFilter)
|
||||
//{
|
||||
// return await _dbSet.IgnoreQueryFilters().Where(deleteFilter).DeleteFromQueryAsync() > 0;
|
||||
//}
|
||||
|
||||
//public async Task<bool> BatchUpdateAsync(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TEntity>> updateFactory)
|
||||
//{
|
||||
// return await _dbSet.IgnoreQueryFilters().Where(where).UpdateFromQueryAsync(updateFactory) > 0;
|
||||
//}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
Reference in New Issue
Block a user