注意:目前批量删除即使已继承 ISoftDelete 的情况下依然会物理删除,所以可以通过批量更新实现逻辑删除。

调用方法:

await projectsRepository.BatchUpdateAsync(x => new Projects { Status = 2 }, x => projectIdList.Contains(x.Id));

以下是批量更新与删除的内部实现。

批量删除:

/// <summary>
/// Deletes all matching entities permanently for given predicate
/// </summary>
/// <typeparam name="TEntity">Entity type</typeparam>
/// <typeparam name="TPrimaryKey">Primary key type</typeparam>
/// <param name="repository">Repository</param>
/// <param name="predicate">Predicate to filter entities</param>
/// <returns></returns>
public static async Task<int> BatchDeleteAsync<TEntity, TPrimaryKey>([NotNull] this IRepository<TEntity, TPrimaryKey> repository, [NotNull] Expression<Func<TEntity, bool>> predicate)where TEntity : Entity<TPrimaryKey>
{Check.NotNull(repository, nameof(repository));Check.NotNull(predicate, nameof(predicate));var query = repository.GetAll().IgnoreQueryFilters();var abpFilterExpression = GetFilterExpressionOrNull<TEntity, TPrimaryKey>(repository.GetIocResolver());var filterExpression = ExpressionCombiner.Combine(predicate, abpFilterExpression);query = query.Where(filterExpression);return await query.DeleteAsync();
}

批量更新:

/// <summary>
/// Updates all matching entities using given updateExpression for given predicate
/// </summary>
/// <typeparam name="TEntity">Entity type</typeparam>
/// <typeparam name="TPrimaryKey">Primary key type</typeparam>
/// <param name="repository">Repository</param>
/// /// <param name="updateExpression">Update expression</param>
/// <param name="predicate">Predicate to filter entities</param>
/// <returns></returns>
public static async Task<int> BatchUpdateAsync<TEntity, TPrimaryKey>([NotNull]this IRepository<TEntity, TPrimaryKey> repository, [NotNull]Expression<Func<TEntity, TEntity>> updateExpression, [NotNull]Expression<Func<TEntity, bool>> predicate)where TEntity : Entity<TPrimaryKey>
{Check.NotNull(repository, nameof(repository));Check.NotNull(updateExpression, nameof(updateExpression));Check.NotNull(predicate, nameof(predicate));var query = repository.GetAll().IgnoreQueryFilters();var abpFilterExpression = GetFilterExpressionOrNull<TEntity, TPrimaryKey>(repository.GetIocResolver());var filterExpression = ExpressionCombiner.Combine(predicate, abpFilterExpression);query = query.Where(filterExpression);return await query.UpdateAsync(updateExpression);
}

ABP 扩展类内部实现:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Abp.Dependency;
using Abp.Domain.Entities;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Linq.Expressions;
using Abp.Runtime.Session;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Z.EntityFramework.Plus;namespace Abp.EntityFrameworkCore.EFPlus
{/// <summary>/// Defines batch delete and update extension methods for IRepository/// </summary>public static class AbpEntityFrameworkCoreEfPlusExtensions{/// <summary>/// Deletes all matching entities permanently for given predicate/// </summary>/// <typeparam name="TEntity">Entity type</typeparam>/// <typeparam name="TPrimaryKey">Primary key type</typeparam>/// <param name="repository">Repository</param>/// <param name="predicate">Predicate to filter entities</param>/// <returns></returns>public static async Task<int> BatchDeleteAsync<TEntity, TPrimaryKey>([NotNull] this IRepository<TEntity, TPrimaryKey> repository, [NotNull] Expression<Func<TEntity, bool>> predicate)where TEntity : Entity<TPrimaryKey>{Check.NotNull(repository, nameof(repository));Check.NotNull(predicate, nameof(predicate));var query = repository.GetAll().IgnoreQueryFilters();var abpFilterExpression = GetFilterExpressionOrNull<TEntity, TPrimaryKey>(repository.GetIocResolver());var filterExpression = ExpressionCombiner.Combine(predicate, abpFilterExpression);query = query.Where(filterExpression);return await query.DeleteAsync();}/// <summary>/// Deletes all matching entities permanently for given predicate/// </summary>/// <typeparam name="TEntity">Entity type</typeparam>/// <param name="repository">Repository</param>/// <param name="predicate">Predicate to filter entities</param>/// <returns></returns>public static async Task<int> BatchDeleteAsync<TEntity>([NotNull] this IRepository<TEntity> repository, [NotNull]Expression<Func<TEntity, bool>> predicate)where TEntity : Entity<int>{return await repository.BatchDeleteAsync<TEntity, int>(predicate);}/// <summary>/// Updates all matching entities using given updateExpression for given predicate/// </summary>/// <typeparam name="TEntity">Entity type</typeparam>/// <typeparam name="TPrimaryKey">Primary key type</typeparam>/// <param name="repository">Repository</param>/// /// <param name="updateExpression">Update expression</param>/// <param name="predicate">Predicate to filter entities</param>/// <returns></returns>public static async Task<int> BatchUpdateAsync<TEntity, TPrimaryKey>([NotNull]this IRepository<TEntity, TPrimaryKey> repository, [NotNull]Expression<Func<TEntity, TEntity>> updateExpression, [NotNull]Expression<Func<TEntity, bool>> predicate)where TEntity : Entity<TPrimaryKey>{Check.NotNull(repository, nameof(repository));Check.NotNull(updateExpression, nameof(updateExpression));Check.NotNull(predicate, nameof(predicate));var query = repository.GetAll().IgnoreQueryFilters();var abpFilterExpression = GetFilterExpressionOrNull<TEntity, TPrimaryKey>(repository.GetIocResolver());var filterExpression = ExpressionCombiner.Combine(predicate, abpFilterExpression);query = query.Where(filterExpression);return await query.UpdateAsync(updateExpression);}/// <summary>/// Updates all matching entities using given updateExpression for given predicate/// </summary>/// <typeparam name="TEntity">Entity type</typeparam>/// <param name="repository">Repository</param>/// /// <param name="updateExpression">Update expression</param>/// <param name="predicate">Predicate to filter entities</param>/// <returns></returns>public static async Task<int> BatchUpdateAsync<TEntity>([NotNull]this IRepository<TEntity> repository, [NotNull]Expression<Func<TEntity, TEntity>> updateExpression,[NotNull]Expression<Func<TEntity, bool>> predicate)where TEntity : Entity<int>{return await repository.BatchUpdateAsync<TEntity, int>(updateExpression, predicate);}private static Expression<Func<TEntity, bool>> GetFilterExpressionOrNull<TEntity, TPrimaryKey>(IIocResolver iocResolver) where TEntity : Entity<TPrimaryKey>{Expression<Func<TEntity, bool>> expression = null;using (var scope = iocResolver.CreateScope()){var currentUnitOfWorkProvider = scope.Resolve<ICurrentUnitOfWorkProvider>();if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))){var isSoftDeleteFilterEnabled = currentUnitOfWorkProvider.Current?.IsFilterEnabled(AbpDataFilters.SoftDelete) == true;if (isSoftDeleteFilterEnabled){Expression<Func<TEntity, bool>> softDeleteFilter = e => !((ISoftDelete)e).IsDeleted;expression = softDeleteFilter;}}if (typeof(IMayHaveTenant).IsAssignableFrom(typeof(TEntity))){var isMayHaveTenantFilterEnabled = currentUnitOfWorkProvider.Current?.IsFilterEnabled(AbpDataFilters.MayHaveTenant) == true;var currentTenantId = GetCurrentTenantIdOrNull(iocResolver);if (isMayHaveTenantFilterEnabled){Expression<Func<TEntity, bool>> mayHaveTenantFilter = e => ((IMayHaveTenant)e).TenantId == currentTenantId;expression = expression == null ? mayHaveTenantFilter : ExpressionCombiner.Combine(expression, mayHaveTenantFilter);}}if (typeof(IMustHaveTenant).IsAssignableFrom(typeof(TEntity))){var isMustHaveTenantFilterEnabled = currentUnitOfWorkProvider.Current?.IsFilterEnabled(AbpDataFilters.MustHaveTenant) == true;var currentTenantId = GetCurrentTenantIdOrNull(iocResolver);if (isMustHaveTenantFilterEnabled){Expression<Func<TEntity, bool>> mustHaveTenantFilter = e => ((IMustHaveTenant)e).TenantId == currentTenantId;expression = expression == null ? mustHaveTenantFilter : ExpressionCombiner.Combine(expression, mustHaveTenantFilter);}}}return expression;}private static int? GetCurrentTenantIdOrNull(IIocResolver iocResolver){using (var scope = iocResolver.CreateScope()){var currentUnitOfWorkProvider = scope.Resolve<ICurrentUnitOfWorkProvider>();if (currentUnitOfWorkProvider?.Current != null){return currentUnitOfWorkProvider.Current.GetTenantId();}return iocResolver.Resolve<IAbpSession>().TenantId;}}}
}

ABP 在 EntityFramework 中使用扩展实现批量操作相关推荐

  1. ABP 在 EntityFramework 中使用扩展批量更新时的异常

    报错信息:Invalid Cast. The update expression must be of type MemberInitExpression. 直译结果:无效的.更新表达式必须是Memb ...

  2. 【ABP杂烩】Extensions后缀扩展方法

    原文:[ABP杂烩]Extensions后缀扩展方法 1.Extensions介绍 扩展方法使你能够向现有类型"添加"方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型 ...

  3. Asp.Net中修改扩展名的问题

    关于Asp.Net中的扩展名修改问题,方法有很多种,而且有比较成熟的第三方组件.这方面的东西在老赵点滴上说的很明白.我在这里给大家介绍一种比较简单的方法通过配置IIS来实现. Framework1.1 ...

  4. FFmpeg从入门到出家(HEVC在RTMP中的扩展)

    由金山云视频云技术团队提供:FFmpeg从入门到出家第三季: 为推进HEVC视频编码格式在直播方案中的落地,经过CDN联盟讨论,并和主流云服务厂商达成一致,规范了HEVC在RTMP/FLV中的扩展,具 ...

  5. 如何修改作者名称_PS2019中如何扩展文本选区 ps扩展文本选区的图文教程_photoshop教程...

    百度经验 发布时间:2020-11-26 17:13:48   作者:twotwoyourfour 我要评论 PS2019中如何扩展文本选区?有时我们在制作文字里需要扩展文字的选区,下文中为大家带来了 ...

  6. pgsql怎么从interval中取出数字_tp6中swoole扩展websocket的使用

    相信不少人都已经知道tp6.0已经适配swoole.并推出think-swoole 3.0 ,这次就来介绍下tp6中swoole扩展websocket的使用. Websocket 继承与Http,进行 ...

  7. fme中oracle转shp,FME中CASS扩展属性转SHP的方法

    原标题:FME中CASS扩展属性转SHP的方法 问题:真受不了CAD中的注记,只能方便显示,难于数据交互.好在CASS把属性信息基本写在扩展属性中,但显示又成问题了.此事难两全!我们通过查看实体属性, ...

  8. FFmpeg代码导读——HEVC在RTMP中的扩展

    视频流媒体中视频数据的传输占据了绝大部分的带宽,如何提升编码效率.减小带宽使用.提升画面质量,成为音视频开发者努力的重点.HEVC编码格式的推出为此带来了突破点.对于直播而言,大部分推拉流协议是基于R ...

  9. FFmpeg代码导读系列(一,下半部)----HEVC在RTMP中的扩展

    金山云多媒体SDK团队在移动直播.短视频等项目中遇到了许多FFmpeg问题,特设立<FFmpeg从入门到出家>系列文稿,希望博君一笑的同时,能让大家对FFmpeg有更深入的了解. 先在前面 ...

最新文章

  1. Java学习总结:13
  2. 在typescript中导入第三方类库import报错
  3. 脚本在流程中的性能影响
  4. try-catch-finally-return执行路径总结
  5. 云锁多机版云中心使用测评
  6. java读取同包文件_Java实现从jar包中读取指定文件的方法
  7. Javascript基于对象三大特征
  8. 无字库12864液晶屏滚动显示程序[转]
  9. 用bcp实现的存储过程 导整个数据库
  10. 优化程序性能(CSAPP)
  11. python 06day --bootstrap框架使用及linux的磁盘管理
  12. NetAssist连接报错!
  13. 甘特图来啦,项目管理神器,模板直接用
  14. ScreenFlow 录制Mac电脑声音
  15. c语言加权成绩,c – 加权中值计算
  16. 五一,读孔明《诫子书》有感
  17. Pixel 3 的最佳照片功能
  18. 假定1km长的CSMA/CD网络的数据率为1Gbit/s。设信号在网络上的传输速率为200000km/s.求能够使用此协议的最短帧长。
  19. java模拟器下载_JAVA模拟器(指小游)
  20. 金彩教育:店铺运营怎么看数据

热门文章

  1. [浙大网新易盛] 程序员你12点前睡觉了吗?
  2. 几楼电路精灵——解决Cadence多版本共存
  3. 如何把微信状态玩出新花样?30秒就能学会的超简单教程
  4. 玉米社:本地区地域性网络营销推广怎么做?
  5. 赤峰学院计算机等级考试,赤峰学院学报(自然科学版
  6. 计算机毕设-JavaWeb在线球鞋销售商城系统代码-在线商城系统-商城系统SpringMVC+Spring+Mybatis
  7. 软件版本和实际有出入导致的后果_【问答】请问报关的数量跟实际装箱的数据有出入的话,会影响客户清关吗? - 邦阅网-外贸知识服务平台...
  8. 考公和大厂40万年薪的offer,选哪个?
  9. 20本机器学习与数据科学必读书籍
  10. 【计算机视觉】相机标定