From 5ee3fc5b79fe90d2c49c705ccdc4f9e28e78b896 Mon Sep 17 00:00:00 2001 From: hang <872297557@qq.com> Date: Wed, 1 Jun 2022 16:13:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BB=93=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Doctor/DoctorTrialState.cs | 30 --- .../Repository/EntityExpression.cs | 35 --- .../Repository/ICommandRepository.cs | 4 +- .../Repository/IRaCISContextExtension.cs | 176 ++++++++++++++++ .../Repository/IRepository.cs | 121 ++--------- .../Repository/Repository.cs | 199 ++++-------------- 6 files changed, 237 insertions(+), 328 deletions(-) delete mode 100644 IRaCIS.Core.Domain.Share/Doctor/DoctorTrialState.cs delete mode 100644 IRaCIS.Core.Infra.EFCore/Repository/EntityExpression.cs create mode 100644 IRaCIS.Core.Infra.EFCore/Repository/IRaCISContextExtension.cs diff --git a/IRaCIS.Core.Domain.Share/Doctor/DoctorTrialState.cs b/IRaCIS.Core.Domain.Share/Doctor/DoctorTrialState.cs deleted file mode 100644 index d7914222c..000000000 --- a/IRaCIS.Core.Domain.Share/Doctor/DoctorTrialState.cs +++ /dev/null @@ -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 - - } -} \ No newline at end of file diff --git a/IRaCIS.Core.Infra.EFCore/Repository/EntityExpression.cs b/IRaCIS.Core.Infra.EFCore/Repository/EntityExpression.cs deleted file mode 100644 index a499febda..000000000 --- a/IRaCIS.Core.Infra.EFCore/Repository/EntityExpression.cs +++ /dev/null @@ -1,35 +0,0 @@ -using IRaCIS.Core.Domain.Models; -using System; -using System.Linq.Expressions; - -namespace IRaCIS.Core.Infra.EFCore -{ - public class EntityVerifyExp where TEntity : Entity - { - //验证表达式树 - public Expression> 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, - } - - - -} - - - - diff --git a/IRaCIS.Core.Infra.EFCore/Repository/ICommandRepository.cs b/IRaCIS.Core.Infra.EFCore/Repository/ICommandRepository.cs index e8e1c940b..0ed738c59 100644 --- a/IRaCIS.Core.Infra.EFCore/Repository/ICommandRepository.cs +++ b/IRaCIS.Core.Infra.EFCore/Repository/ICommandRepository.cs @@ -41,7 +41,7 @@ namespace IRaCIS.Core.Infra.EFCore Task UpdateAsync(TEntity entity, Expression> updateFactory, bool autoSave = false, CancellationToken cancellationToken = default); - /// EF跟踪方式 先查询出来,再更新部分字段 + /// EF跟踪方式 会去数据库查询完整的实体,再更新部分字段 Task UpdatePartialFromQueryAsync(Guid id, Expression> updateFactory, bool autoSave = false, bool ignoreQueryFilter = false, CancellationToken cancellationToken = default); @@ -93,7 +93,7 @@ namespace IRaCIS.Core.Infra.EFCore /// /// /// - Task FirstAsync(Expression> exp = null, bool isTracking = false); + Task FirstAsync(Expression> exp = null, bool isTracking = false,bool ignoreQueryFilters = false); /// ///跟踪 查询单个实体,会出现NUll diff --git a/IRaCIS.Core.Infra.EFCore/Repository/IRaCISContextExtension.cs b/IRaCIS.Core.Infra.EFCore/Repository/IRaCISContextExtension.cs new file mode 100644 index 000000000..3b472541e --- /dev/null +++ b/IRaCIS.Core.Infra.EFCore/Repository/IRaCISContextExtension.cs @@ -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 where TEntity : Entity + { + //验证表达式树 + public Expression> 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 + { + /// + ///添加和更新的时候,通常需要与数据库已存在的数据进行校验,添加更新的区分在于是否需要排除自己 + /// + /// + /// + /// + /// + /// + /// + /// + public static async Task EntityVerifyAsync(this IRaCISDBContext _dbContext, bool isAdd, EntityVerifyExp[] 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().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().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false)) + { + throw new BusinessValidationFailedException(verifyItem.VerifyMsg); + } + } + else if (verifyItem.verifyType == VerifyEnum.Both) + { + if (await _dbContext.Set().AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entitydId)).ConfigureAwait(false)) + { + throw new BusinessValidationFailedException(verifyItem.VerifyMsg); + } + } + } + } + } + + ///注意 模型标注了 ConcurrencyCheck的属性,这样的实体,不适合用部分字段更新,ef生成的更新sql会自动带上ConcurrencyCheck的属性条件 + /// EntityState.Detached的实体 修改 部分字段 + public static void EntityModifyPartialFiled(this IRaCISDBContext _dbContext,T waitModifyEntity, Expression> 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 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 跟踪机制的删除 更新 以及批量操作 + + /// 批量删除,相当于原生sql, 没用EF跟踪方式(所有查询出来,再删除 浪费性能) + public static async Task BatchDeleteNoTrackingAsync(this IRaCISDBContext _dbContext,Expression> deleteFilter) where T : Entity + { + if (deleteFilter == null) throw new ArgumentNullException(nameof(deleteFilter)); + + return await _dbContext.Set().IgnoreQueryFilters().Where(deleteFilter).BatchDeleteAsync() > 0; + } + + + /// 批量更新,相当于原生sql, 没用EF跟踪方式(所有查询出来,再更新 浪费性能) + public static async Task BatchUpdateNoTrackingAsync(this IRaCISDBContext _dbContext,Expression> where, Expression> 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>(member, Expression.Parameter(typeof(T), "x")); + + + return await _dbContext.Set().IgnoreQueryFilters().Where(where).BatchUpdateAsync(factory).ConfigureAwait(false) > 0; + + + + } + + #endregion + } + + + + + + +} + + + + diff --git a/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs b/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs index 83b95d08c..b772400b0 100644 --- a/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs +++ b/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs @@ -23,7 +23,7 @@ namespace IRaCIS.Core.Infra.EFCore public interface IRepository { - IQueryable GetQueryable(bool isTraking = false) where T : Entity; + IQueryable GetQueryable(bool ignoreQueryFilters = false) where T : Entity; DbSet Set() where T : Entity; EntityEntry Entry(T t) where T : Entity; @@ -92,15 +92,15 @@ namespace IRaCIS.Core.Infra.EFCore /// /// - public IQueryable GetQueryable(bool isTraking = false) where T : Entity + public IQueryable GetQueryable(bool ignoreQueryFilters = false) where T : Entity { IQueryable query = _dbContext.Set(); - if (!isTraking) + if (ignoreQueryFilters) { - query = query.AsNoTracking(); + query = query.IgnoreQueryFilters(); } - return query; + return query.AsNoTracking(); } public DbSet Set() where T : Entity { @@ -141,49 +141,13 @@ namespace IRaCIS.Core.Infra.EFCore - private async Task EntityVerifyAsync(bool isAdd, EntityVerifyExp[] 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().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().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false)) - { - throw new BusinessValidationFailedException(verifyItem.VerifyMsg); - } - } - else if (verifyItem.verifyType == VerifyEnum.Both) - { - if (await _dbContext.Set().AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entitydId)).ConfigureAwait(false)) - { - throw new BusinessValidationFailedException(verifyItem.VerifyMsg); - } - } - } - } - - } - public async Task InsertFromDTOAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity { var entity = _mapper.Map(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(from); - await EntityVerifyAsync(false, verify, entity.Id); + + await _dbContext.EntityVerifyAsync(false, verify, entity.Id); var dbEntity = await _dbContext.Set().IgnoreQueryFilters().FirstOrDefaultAsync(t => t.Id == entity.Id).ConfigureAwait(false); @@ -359,10 +324,7 @@ namespace IRaCIS.Core.Infra.EFCore await _dbContext.Set().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 BatchDeleteAsync(Expression> deleteFilter) where T : Entity { - if (deleteFilter == null) throw new ArgumentNullException(nameof(deleteFilter)); - - return await _dbContext.Set().AsNoTracking().IgnoreQueryFilters().Where(deleteFilter).BatchDeleteAsync().ConfigureAwait(false) > 0; + return await _dbContext.BatchDeleteNoTrackingAsync(deleteFilter); } public async Task BatchUpdateAsync(Expression> whereFilter, Expression> 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>(member, Expression.Parameter(typeof(T), "x")); - - return await _dbContext.Set().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 UpdateAsync(T waitModifyEntity, Expression> 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); } - /// 更新后拥有完整的实体信息,便于稽查 - private void ModifyPartialFiled(T waitModifyEntity, Expression> updateFactory) - { - List list = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name) - .Select(propName => typeof(T).GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)).ToList(); - Func 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 diff --git a/IRaCIS.Core.Infra.EFCore/Repository/Repository.cs b/IRaCIS.Core.Infra.EFCore/Repository/Repository.cs index e08eeb0e4..5ef40c16f 100644 --- a/IRaCIS.Core.Infra.EFCore/Repository/Repository.cs +++ b/IRaCIS.Core.Infra.EFCore/Repository/Repository.cs @@ -43,6 +43,8 @@ namespace IRaCIS.Core.Infra.EFCore } + + #region 异步 EF 跟踪 添加 public async Task> AddRangeAsync(IEnumerable entities, bool autoSave = false) { @@ -70,7 +72,7 @@ namespace IRaCIS.Core.Infra.EFCore public async Task InsertFromDTOAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) { - await EntityVerifyAsync(true, verify); + await _dbContext.EntityVerifyAsync(true, verify); var entity = _mapper.Map(from); @@ -93,7 +95,9 @@ namespace IRaCIS.Core.Infra.EFCore var entity = _mapper.Map(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 - /// EF跟踪方式 生成 部分字段更新, 通过主键id 和表达式树 更新部分字段 - /// 例如 Guid.Parse("8a90c96e-0776-4f7b-82a6-18933d339584"),u => new Dictionary() { ParentId = null, Code = "test" }默认会去处理更新更新人 更新时间 + /// EF跟踪方式 生成 部分字段更新, 跟踪的实体仅有修改的属性的值有具体意义,没有从数据库查询完整的实体 public async Task UpdatePartialNoQueryAsync(Guid id, Expression> updateFactory, bool autoSave = false, params EntityVerifyExp[] 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 UpdatePartialNowNoQueryAsync(Guid id, Expression> updateFactory, params EntityVerifyExp[] 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); } - /// 注意 模型标注了 ConcurrencyCheck的属性,这样的实体,不适合用部分字段更新,ef生成的更新sql会自动带上ConcurrencyCheck的属性条件 - private async Task SetPartialFieldUpdateAsync(Guid id, Expression> updateFactory, params EntityVerifyExp[] verify) - { - await EntityVerifyAsync(false, verify, id); - - var entity = new TEntity() { Id = id }; - - var entityEntry = _dbContext.Entry(entity); - - entityEntry.State = EntityState.Detached; - - - List list = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name) - .Select(propName => typeof(TEntity).GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)).ToList(); - - Func 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 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); } /// EF跟踪方式 外层先有查询好的完成实体,再更新部分字段 稽查的时候需要完整的实体信息 public async Task UpdateAsync(TEntity waitModifyEntity, Expression> 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); + } - /// 更新后拥有完整的实体信息,便于稽查 - private void ModifyPartialFiled(TEntity waitModifyEntity, Expression> updateFactory) - { - List list = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name) - .Select(propName => typeof(TEntity).GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)).ToList(); - - Func 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; - } - - - } /// EF跟踪方式 删除 @@ -368,7 +309,9 @@ namespace IRaCIS.Core.Infra.EFCore /// 批量删除,相当于原生sql, 没用EF跟踪方式(所有查询出来,再删除 浪费性能) public async Task BatchDeleteNoTrackingAsync(Expression> deleteFilter) { - return await _dbSet.IgnoreQueryFilters().Where(deleteFilter).BatchDeleteAsync() > 0; + + return await _dbContext.BatchDeleteNoTrackingAsync(deleteFilter); + } @@ -377,42 +320,15 @@ namespace IRaCIS.Core.Infra.EFCore Expression> 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>(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 InsertOrUpdateAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) { @@ -428,41 +344,7 @@ namespace IRaCIS.Core.Infra.EFCore return await UpdateFromDTOAsync(from, autoSave, false, verify); } } - private async Task EntityVerifyAsync(bool isAdd, EntityVerifyExp[] 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 SaveChangesAsync(bool autoSave) { @@ -523,7 +405,8 @@ namespace IRaCIS.Core.Infra.EFCore public async Task UpdatePartialFieldsAsync(TEntity entity, string[] propertyNames, bool autoSave = false, bool ignoreEntityNullProperty = true, params EntityVerifyExp[] 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 /// 更新 排除某些字段的更新 排除方式: new[] {nameof(User.Name), nameof(User.Age) public async Task UpdateExcludeFields(TEntity entity, string[] propertyNames, bool autoSave = false, bool ignoreEntityNullProperty = true, params EntityVerifyExp[] 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 FirstAsync(Expression> exp = null, bool isTracking = false) + public async Task FirstAsync(Expression> 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)