整理仓储

Uat_Study
hang 2022-06-01 16:13:44 +08:00
parent d1ce475e9c
commit 5ee3fc5b79
6 changed files with 237 additions and 328 deletions

View File

@ -1,30 +0,0 @@
namespace IRaCIS.Core.Domain.Share
{
public enum DoctorTrialState
{
NotApply = 0,
//已申请
HasAppliedDownLoad = 1,
//审核通过
AuditPass = 2,
AuditFailed = 3,
//已下载
ResumeHasDownLoad = 4,
//已邀请--已确认该名单
Inviting = 5,
//同意入组
InviteConfirmed = 6,
//拒绝入组
InviteRefused = 7,
HasUploadAgreement = 8
}
}

View File

@ -1,35 +0,0 @@
using IRaCIS.Core.Domain.Models;
using System;
using System.Linq.Expressions;
namespace IRaCIS.Core.Infra.EFCore
{
public class EntityVerifyExp<TEntity> where TEntity : Entity
{
//验证表达式树
public Expression<Func<TEntity, bool>> VerifyExp { get; set; }
//验证提示错误信息
public string VerifyMsg { get; set; }
public VerifyEnum verifyType { get; set; } = VerifyEnum.Both;
public bool IsVerify { get; set; } = true;
}
public enum VerifyEnum
{
OnlyAdd = 1,
OnlyUpdate = 2,
Both = 3,
}
}

View File

@ -41,7 +41,7 @@ namespace IRaCIS.Core.Infra.EFCore
Task<bool> UpdateAsync(TEntity entity, Expression<Func<TEntity, TEntity>> updateFactory,
bool autoSave = false, CancellationToken cancellationToken = default);
/// <summary> EF跟踪方式 先查询出来,再更新部分字段 </summary>
/// <summary> EF跟踪方式 会去数据库查询完整的实体,再更新部分字段 </summary>
Task<TEntity> UpdatePartialFromQueryAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory,
bool autoSave = false, bool ignoreQueryFilter = false, CancellationToken cancellationToken = default);
@ -93,7 +93,7 @@ namespace IRaCIS.Core.Infra.EFCore
/// <param name="exp"></param>
/// <param name="ignoreQueryFilters"></param>
/// <returns></returns>
Task<TEntity> FirstAsync(Expression<Func<TEntity, bool>> exp = null, bool isTracking = false);
Task<TEntity> FirstAsync(Expression<Func<TEntity, bool>> exp = null, bool isTracking = false,bool ignoreQueryFilters = false);
/// <summary>
///跟踪 查询单个实体会出现NUll

View File

@ -0,0 +1,176 @@
using EFCore.BulkExtensions;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
namespace IRaCIS.Core.Infra.EFCore
{
public class EntityVerifyExp<TEntity> where TEntity : Entity
{
//验证表达式树
public Expression<Func<TEntity, bool>> VerifyExp { get; set; }
//验证提示错误信息
public string VerifyMsg { get; set; }
public VerifyEnum verifyType { get; set; } = VerifyEnum.Both;
public bool IsVerify { get; set; } = true;
}
public enum VerifyEnum
{
OnlyAdd = 1,
OnlyUpdate = 2,
Both = 3,
}
public static class EntityAction
{
/// <summary>
///添加和更新的时候,通常需要与数据库已存在的数据进行校验,添加更新的区分在于是否需要排除自己
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="_dbContext"></param>
/// <param name="isAdd"></param>
/// <param name="verify"></param>
/// <param name="entitydId"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
public static async Task EntityVerifyAsync<T>(this IRaCISDBContext _dbContext, bool isAdd, EntityVerifyExp<T>[] verify, Guid? entitydId = null) where T : Entity
{
if (isAdd)
{
foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyUpdate && t.IsVerify))
{
if (await _dbContext.Set<T>().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
}
else
{
foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyAdd && t.IsVerify))
{
if (verifyItem.verifyType == VerifyEnum.OnlyUpdate)
{
if (await _dbContext.Set<T>().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
else if (verifyItem.verifyType == VerifyEnum.Both)
{
if (await _dbContext.Set<T>().AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entitydId)).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
}
}
}
///注意 模型标注了 ConcurrencyCheck的属性这样的实体不适合用部分字段更新ef生成的更新sql会自动带上ConcurrencyCheck的属性条件
/// <summary>EntityState.Detached的实体 修改 部分字段</summary>
public static void EntityModifyPartialFiled<T>(this IRaCISDBContext _dbContext,T waitModifyEntity, Expression<Func<T, T>> updateFactory) where T : Entity
{
var entityEntry = _dbContext.Entry(waitModifyEntity);
entityEntry.State = EntityState.Detached;
var list = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name)
.Select(propName => typeof(T).GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)).ToList();
Func<T, T> func = updateFactory.Compile();
T applyObj = func(waitModifyEntity);
//深拷贝更新之前实体信息
//var copyObj = waitModifyEntity.Clone();
foreach (PropertyInfo prop in list)
{
object value = prop.GetValue(applyObj);
prop.SetValue(waitModifyEntity, value);
_dbContext.Entry(waitModifyEntity).Property(prop.Name).IsModified = true;
}
}
#region 不走EF 跟踪机制的删除 更新 以及批量操作
/// <summary>批量删除相当于原生sql 没用EF跟踪方式所有查询出来再删除 浪费性能)</summary>
public static async Task<bool> BatchDeleteNoTrackingAsync<T>(this IRaCISDBContext _dbContext,Expression<Func<T, bool>> deleteFilter) where T : Entity
{
if (deleteFilter == null) throw new ArgumentNullException(nameof(deleteFilter));
return await _dbContext.Set<T>().IgnoreQueryFilters().Where(deleteFilter).BatchDeleteAsync() > 0;
}
/// <summary>批量更新相当于原生sql 没用EF跟踪方式所有查询出来再更新 浪费性能)</summary>
public static async Task<bool> BatchUpdateNoTrackingAsync<T>(this IRaCISDBContext _dbContext,Expression<Func<T, bool>> where, Expression<Func<T, T>> updateFactory,Guid updateUserId) where T : Entity
{
if (where == null) throw new ArgumentNullException(nameof(where));
var bindings = ((MemberInitExpression)updateFactory.Body).Bindings.ToList();
var hasPropNameList = bindings.Select(t => t.Member.Name).ToList();
if (typeof(IAuditUpdate).IsAssignableFrom(typeof(T)))
{
if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateTime)))
{
bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateTime))[0], Expression.Constant(DateTime.Now)));
}
if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateUserId)))
{
bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateUserId))[0], Expression.Constant(updateUserId)));
}
}
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>().IgnoreQueryFilters().Where(where).BatchUpdateAsync(factory).ConfigureAwait(false) > 0;
}
#endregion
}
}

View File

@ -23,7 +23,7 @@ namespace IRaCIS.Core.Infra.EFCore
public interface IRepository
{
IQueryable<T> GetQueryable<T>(bool isTraking = false) where T : Entity;
IQueryable<T> GetQueryable<T>(bool ignoreQueryFilters = false) where T : Entity;
DbSet<T> Set<T>() where T : Entity;
EntityEntry<T> Entry<T>(T t) where T : Entity;
@ -92,15 +92,15 @@ namespace IRaCIS.Core.Infra.EFCore
/// <param name="isTraking"></param>
/// <returns></returns>
public IQueryable<T> GetQueryable<T>(bool isTraking = false) where T : Entity
public IQueryable<T> GetQueryable<T>(bool ignoreQueryFilters = false) where T : Entity
{
IQueryable<T> query = _dbContext.Set<T>();
if (!isTraking)
if (ignoreQueryFilters)
{
query = query.AsNoTracking();
query = query.IgnoreQueryFilters();
}
return query;
return query.AsNoTracking();
}
public DbSet<T> Set<T>() where T : Entity
{
@ -141,49 +141,13 @@ namespace IRaCIS.Core.Infra.EFCore
private async Task EntityVerifyAsync<T>(bool isAdd, EntityVerifyExp<T>[] verify, Guid? entitydId = null) where T : Entity
{
if (isAdd)
{
foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyUpdate && t.IsVerify))
{
if (await _dbContext.Set<T>().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
}
else
{
foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyAdd && t.IsVerify))
{
if (verifyItem.verifyType == VerifyEnum.OnlyUpdate)
{
if (await _dbContext.Set<T>().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
else if (verifyItem.verifyType == VerifyEnum.Both)
{
if (await _dbContext.Set<T>().AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entitydId)).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
}
}
}
public async Task<T> InsertFromDTOAsync<T, TFrom>(TFrom from, bool autoSave = false,
params EntityVerifyExp<T>[] verify) where T : Entity
{
var entity = _mapper.Map<T>(from);
await EntityVerifyAsync(true, verify);
await _dbContext.EntityVerifyAsync(true, verify);
entity = await AddAsync(entity, autoSave);
@ -195,7 +159,8 @@ namespace IRaCIS.Core.Infra.EFCore
{
var entity = _mapper.Map<T>(from);
await EntityVerifyAsync(false, verify, entity.Id);
await _dbContext.EntityVerifyAsync(false, verify, entity.Id);
var dbEntity = await _dbContext.Set<T>().IgnoreQueryFilters().FirstOrDefaultAsync(t => t.Id == entity.Id).ConfigureAwait(false);
@ -359,10 +324,7 @@ namespace IRaCIS.Core.Infra.EFCore
await _dbContext.Set<T>().AddAsync(entity).ConfigureAwait(false);
if (autoSave)
{
await SaveChangesAsync();
}
await SaveChangesAsync(autoSave);
return entity;
}
@ -412,41 +374,14 @@ namespace IRaCIS.Core.Infra.EFCore
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().IgnoreQueryFilters().Where(deleteFilter).BatchDeleteAsync().ConfigureAwait(false) > 0;
return await _dbContext.BatchDeleteNoTrackingAsync(deleteFilter);
}
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));
var bindings = ((MemberInitExpression)updateFactory.Body).Bindings.ToList();
if (typeof(IAuditUpdate).IsAssignableFrom(typeof(T)))
{
var hasPropNameList = bindings.Select(t => t.Member.Name).ToList();
if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateTime)))
{
bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateTime))[0], Expression.Constant(DateTime.Now)));
}
if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateUserId)))
{
bindings.Add(Expression.Bind(typeof(T).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;
return await _dbContext.BatchUpdateNoTrackingAsync(whereFilter, updateFactory, _userInfo.Id);
}
@ -464,46 +399,22 @@ namespace IRaCIS.Core.Infra.EFCore
foreach (var needUpdateEntity in searchEntityList)
{
await UpdateAsync(needUpdateEntity, updateFactory, autoSave);
_dbContext.EntityModifyPartialFiled(needUpdateEntity, updateFactory);
}
await SaveChangesAsync(autoSave);
}
public async Task<bool> UpdateAsync<T>(T waitModifyEntity, Expression<Func<T, T>> updateFactory, bool autoSave = false) where T : Entity
{
var entityEntry = _dbContext.Entry(waitModifyEntity);
entityEntry.State = EntityState.Detached;
ModifyPartialFiled(waitModifyEntity, updateFactory);
_dbContext.EntityModifyPartialFiled(waitModifyEntity, updateFactory);
return await SaveChangesAsync(autoSave);
}
/// <summary>更新后拥有完整的实体信息,便于稽查</summary>
private void ModifyPartialFiled<T>(T waitModifyEntity, Expression<Func<T, T>> updateFactory)
{
List<PropertyInfo> list = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name)
.Select(propName => typeof(T).GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)).ToList();
Func<T, T> func = updateFactory.Compile();
T applyObj = func(waitModifyEntity);
//深拷贝更新之前实体信息
//var copyObj = waitModifyEntity.Clone();
foreach (PropertyInfo prop in list)
{
object value = prop.GetValue(applyObj);
prop.SetValue(waitModifyEntity, value);
_dbContext.Entry(waitModifyEntity).Property(prop.Name).IsModified = true;
}
}
}
#endregion

View File

@ -43,6 +43,8 @@ namespace IRaCIS.Core.Infra.EFCore
}
#region 异步 EF 跟踪 添加
public async Task<IEnumerable<TEntity>> AddRangeAsync(IEnumerable<TEntity> entities, bool autoSave = false)
{
@ -70,7 +72,7 @@ namespace IRaCIS.Core.Infra.EFCore
public async Task<TEntity> InsertFromDTOAsync<TFrom>(TFrom from, bool autoSave = false, params EntityVerifyExp<TEntity>[] verify)
{
await EntityVerifyAsync(true, verify);
await _dbContext.EntityVerifyAsync(true, verify);
var entity = _mapper.Map<TEntity>(from);
@ -93,7 +95,9 @@ namespace IRaCIS.Core.Infra.EFCore
var entity = _mapper.Map<TEntity>(from);
await EntityVerifyAsync(false, verify, entity.Id);
//await EntityVerifyAsync(false, verify, entity.Id);
await _dbContext.EntityVerifyAsync(false, verify, entity.Id);
var dbEntity = await _dbSet.IgnoreQueryFilters().FirstOrDefaultAsync(t => t.Id == entity.Id).ConfigureAwait(false);
@ -131,12 +135,18 @@ namespace IRaCIS.Core.Infra.EFCore
/// <summary> EF跟踪方式 生成 部分字段更新, 通过主键id 和表达式树 更新部分字段
/// 例如 Guid.Parse("8a90c96e-0776-4f7b-82a6-18933d339584"),u => new Dictionary() { ParentId = null, Code = "test" }默认会去处理更新更新人 更新时间</summary>
/// <summary> EF跟踪方式 生成 部分字段更新, 跟踪的实体仅有修改的属性的值有具体意义,没有从数据库查询完整的实体</summary>
public async Task UpdatePartialNoQueryAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory, bool autoSave = false, params EntityVerifyExp<TEntity>[] verify)
{
await SetPartialFieldUpdateAsync(id, updateFactory, verify);
await _dbContext.EntityVerifyAsync(false, verify, id);
var entity = new TEntity() { Id = id };
_dbContext.EntityModifyPartialFiled(entity, updateFactory);
await SaveChangesAsync(autoSave);
@ -147,52 +157,16 @@ namespace IRaCIS.Core.Infra.EFCore
public async Task<bool> UpdatePartialNowNoQueryAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory,
params EntityVerifyExp<TEntity>[] verify)
{
await SetPartialFieldUpdateAsync(id, updateFactory, verify);
await _dbContext.EntityVerifyAsync(false, verify, id);
var entity = new TEntity() { Id = id };
_dbContext.EntityModifyPartialFiled(entity, updateFactory);
return await SaveChangesAsync(true);
}
/// <summary>注意 模型标注了 ConcurrencyCheck的属性这样的实体不适合用部分字段更新ef生成的更新sql会自动带上ConcurrencyCheck的属性条件</summary>
private async Task SetPartialFieldUpdateAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory, 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;
}
#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
}
#endregion
@ -206,25 +180,15 @@ namespace IRaCIS.Core.Infra.EFCore
{
_dbSet.Update(entity);
if (autoSave)
{
return await SaveChangesAsync(cancellationToken);
}
else
{
return false;
}
return await SaveChangesAsync(autoSave);
}
/// <summary>EF跟踪方式 外层先有查询好的完成实体,再更新部分字段 稽查的时候需要完整的实体信息</summary>
public async Task<bool> UpdateAsync(TEntity waitModifyEntity, Expression<Func<TEntity, TEntity>> updateFactory, bool autoSave = false, CancellationToken cancellationToken = default)
{
var entityEntry = _dbContext.Entry(waitModifyEntity);
entityEntry.State = EntityState.Detached;
ModifyPartialFiled(waitModifyEntity, updateFactory);
_dbContext.EntityModifyPartialFiled(waitModifyEntity, updateFactory);
return await SaveChangesAsync(autoSave);
@ -238,7 +202,7 @@ namespace IRaCIS.Core.Infra.EFCore
var query = ignoreQueryFilter ? _dbSet.AsNoTracking().IgnoreQueryFilters() : _dbSet.AsNoTracking();
//不跟踪 查询出来的实体就是Detached
var searchEntity = await query.IgnoreQueryFilters().FirstOrDefaultAsync(t => t.Id == id);
var searchEntity = await query.FirstOrDefaultAsync(t => t.Id == id);
if (searchEntity == null)
{
@ -246,9 +210,7 @@ namespace IRaCIS.Core.Infra.EFCore
" Update object not exist in db,Please check if the parameter Id is passed incorrectly");
}
ModifyPartialFiled(searchEntity, updateFactory);
_dbContext.EntityModifyPartialFiled(searchEntity, updateFactory);
await SaveChangesAsync(autoSave);
@ -269,35 +231,14 @@ namespace IRaCIS.Core.Infra.EFCore
foreach (var needUpdateEntity in searchEntityList)
{
await UpdateAsync(needUpdateEntity, updateFactory, autoSave);
await UpdateAsync(needUpdateEntity, updateFactory, false);
}
await SaveChangesAsync(autoSave);
}
/// <summary>更新后拥有完整的实体信息,便于稽查</summary>
private void ModifyPartialFiled(TEntity waitModifyEntity, Expression<Func<TEntity, TEntity>> updateFactory)
{
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(waitModifyEntity);
//深拷贝更新之前实体信息
//var copyObj = waitModifyEntity.Clone();
foreach (PropertyInfo prop in list)
{
object value = prop.GetValue(applyObj);
prop.SetValue(waitModifyEntity, value);
_dbContext.Entry(waitModifyEntity).Property(prop.Name).IsModified = true;
}
}
/// <summary>EF跟踪方式 删除</summary>
@ -368,7 +309,9 @@ namespace IRaCIS.Core.Infra.EFCore
/// <summary>批量删除相当于原生sql 没用EF跟踪方式所有查询出来再删除 浪费性能)</summary>
public async Task<bool> BatchDeleteNoTrackingAsync(Expression<Func<TEntity, bool>> deleteFilter)
{
return await _dbSet.IgnoreQueryFilters().Where(deleteFilter).BatchDeleteAsync() > 0;
return await _dbContext.BatchDeleteNoTrackingAsync(deleteFilter);
}
@ -377,42 +320,15 @@ namespace IRaCIS.Core.Infra.EFCore
Expression<Func<TEntity, TEntity>> updateFactory)
{
var bindings = ((MemberInitExpression)updateFactory.Body).Bindings.ToList();
var hasPropNameList = bindings.Select(t => t.Member.Name).ToList();
if (typeof(IAuditUpdate).IsAssignableFrom(typeof(TEntity)))
{
if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateTime)))
{
bindings.Add(Expression.Bind(typeof(TEntity).GetMember(nameof(IAuditUpdate.UpdateTime))[0], Expression.Constant(DateTime.Now)));
}
if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateUserId)))
{
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;
return await _dbContext.BatchUpdateNoTrackingAsync(where, updateFactory,_userInfo.Id);
}
#endregion
#region 保存 、忽略 、验证
public async Task<TEntity> InsertOrUpdateAsync<TFrom>(TFrom from, bool autoSave = false, params EntityVerifyExp<TEntity>[] verify)
{
@ -428,41 +344,7 @@ namespace IRaCIS.Core.Infra.EFCore
return await UpdateFromDTOAsync(from, autoSave, false, verify);
}
}
private async Task EntityVerifyAsync(bool isAdd, EntityVerifyExp<TEntity>[] verify, Guid? entitydId = null)
{
if (isAdd)
{
foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyUpdate && t.IsVerify))
{
if (await _dbSet.AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
}
else
{
foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyAdd && t.IsVerify))
{
if (verifyItem.verifyType == VerifyEnum.OnlyUpdate)
{
if (await _dbSet.AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
else if (verifyItem.verifyType == VerifyEnum.Both)
{
if (await _dbSet.AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entitydId)).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
}
}
}
private async Task<bool> SaveChangesAsync(bool autoSave)
{
@ -523,7 +405,8 @@ namespace IRaCIS.Core.Infra.EFCore
public async Task<TEntity> UpdatePartialFieldsAsync(TEntity entity, string[] propertyNames,
bool autoSave = false, bool ignoreEntityNullProperty = true, params EntityVerifyExp<TEntity>[] verify)
{
await EntityVerifyAsync(false, verify, entity.Id);
await _dbContext.EntityVerifyAsync(false, verify, entity.Id);
var entityEntry = _dbContext.Entry(entity);
entityEntry.State = EntityState.Detached;
@ -543,8 +426,7 @@ namespace IRaCIS.Core.Infra.EFCore
/// <summary>更新 排除某些字段的更新 排除方式: new[] {nameof(User.Name), nameof(User.Age)</summary>
public async Task<TEntity> UpdateExcludeFields(TEntity entity, string[] propertyNames, bool autoSave = false, bool ignoreEntityNullProperty = true, params EntityVerifyExp<TEntity>[] verify)
{
await EntityVerifyAsync(false, verify, entity.Id);
await _dbContext.EntityVerifyAsync(false, verify, entity.Id);
var entityEntry = _dbContext.Entry(entity);
entityEntry.State = EntityState.Modified;
@ -611,7 +493,7 @@ namespace IRaCIS.Core.Infra.EFCore
}
public async Task<TEntity> FirstAsync(Expression<Func<TEntity, bool>> exp = null, bool isTracking = false)
public async Task<TEntity> FirstAsync(Expression<Func<TEntity, bool>> exp = null, bool isTracking = false, bool ignoreQueryFilters = false)
{
var query = _dbSet.AsQueryable();
@ -621,6 +503,11 @@ namespace IRaCIS.Core.Infra.EFCore
query = query.AsNoTracking();
}
if (ignoreQueryFilters)
{
query = query.IgnoreQueryFilters();
}
var entity = await query.FirstOrDefaultAsync();
if (entity is null)