当前位置:网站首页>ABP中的数据过滤器 (转载非原创)
ABP中的数据过滤器 (转载非原创)
2022-08-09 12:21:00 【wxilejun】
本文首先介绍了ABP内置的软删除过滤器(ISoftDelete)和多租户过滤器(IMultiTenant),然后介绍了如何实现一个自定义过滤器,最后介绍了在软件开发过程中遇到的实际问题,同时给出了解决问题的一个未必最优的思路。
一.预定义过滤器
ABP中的数据过滤器源码在Volo.Abp.Data[2]包中,官方定义了2个开箱即用的过滤器,分别是软删除过滤器(ISoftDelete)和多租户过滤器(IMultiTenant),想必大家对这2个内置的过滤器已经比较熟悉了。下面重点说下通过IDataFilter实现局部过滤,和通过AbpDataFilterOptions实现全局过滤。
1.IDataFilter局部过滤
主要的思路就是通过IDataFilter依赖注入,然后通过_dataFilter.Disable<XXX>()
临时的启用或者禁用过滤器:
namespace Acme.BookStore
{
public class MyBookService : ITransientDependency
{
private readonly IDataFilter _dataFilter;
private readonly IRepository<Book, Guid> _bookRepository;
public MyBookService(IDataFilter dataFilter, IRepository<Book, Guid> bookRepository)
{
_dataFilter = dataFilter;
_bookRepository = bookRepository;
}
public async Task<List<Book>> GetAllBooksIncludingDeletedAsync()
{
// 临时禁用ISoftDelete过滤器
using (_dataFilter.Disable<ISoftDelete>())
{
return await _bookRepository.GetListAsync();
}
}
}
}
这样就会局部地把IsDeleted=1的记录查找出来。
2.AbpDataFilterOptions全局过滤
主要是通过选项(Options)的方式来配置全局过滤:
Configure<AbpDataFilterOptions>(options =>
{
options.DefaultStates[typeof(ISoftDelete)] = new DataFilterState(isEnabled: false);
});
这样就会全局地把IsDeleted=1的记录查找出来。其中的一个问题是,这段代码写到哪里呢?自己是写到XXX.Host->XXXHostModule->ConfigureServices中,比如Business.Host->BusinessHostModule->ConfigureServices。
二.自定义过滤器
自定义过滤器是比较简单的,基本上都是八股文格式了,对于EFCore来说,就是重写DbContext中的ShouldFilterEntity和CreateFilterExpression方法。因为暂时用不到MongoDB,所以不做介绍,有兴趣可以参考[1],也不是很难。下面通过一个例子来介绍下EF Core的自定义过滤器。
1.定义过滤器接口
首先定义一个过滤器接口,然后实现该接口:
public interface IIsActive
{
bool IsActive { get; }
}
public class Book : AggregateRoot<Guid>, IIsActive
{
public string Name { get; set; }
public bool IsActive { get; set; } //Defined by IIsActive
}
2.重写DbContext中的方法
然后就是重写DbContext中的ShouldFilterEntity和CreateFilterExpression方法:
protected bool IsActiveFilterEnabled => DataFilter?.IsEnabled<IIsActive>() ?? false;
protected override bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType)
{
if (typeof(IIsActive).IsAssignableFrom(typeof(TEntity)))
{
return true;
}
return base.ShouldFilterEntity<TEntity>(entityType);
}
protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
{
var expression = base.CreateFilterExpression<TEntity>();
if (typeof(IIsActive).IsAssignableFrom(typeof(TEntity)))
{
Expression<Func<TEntity, bool>> isActiveFilter = e => !IsActiveFilterEnabled || EF.Property<bool>(e, "IsActive");
expression = expression == null ? isActiveFilter : CombineExpressions(expression, isActiveFilter);
}
return expression;
}
突然看上去觉得这个自定义过滤器好复杂,后来想想那ABP内置的软删除过滤器(ISoftDelete)和多租户过滤器(IMultiTenant)是如何实现的呢?然后就找到了源码ABP/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
:
看了源码实现后会发现格式一模一样,所以自定义过滤器使用起来没有这么复杂。
三.遇到的实际问题
假如在SaaS系统中,有一个主中心和分中心的概念,什么意思呢?就是在主中心中可以看到所有分中心的User数据,同时主中心可以把一些通用的资料(比如,科普文章)共享给分中心。在ABP群里问了下,有人建议宿主就是宿主,用来做租户管理的,不能把它当成一个租户,这是一个父子租户的问题。有人建议搞一个仿租户ID过滤器,这样既能曲线解决问题,又不背离宿主和租户的原则。父子租户第一次听说,所以暂不考虑。因为系统已经开发了一部分,如果每个实体都继承仿租户ID过滤器接口,那么也觉得麻烦。 最终选择把主中心当成是宿主用户,分中心当成是租户。对于一些通用的资料(比如,科普文章),在增删改查中直接IDataFilter局部过滤。比如查找实现如下:
public async Task<PagedResultDto<ArticleDto>> GetAll(GetArticleInputDto input)
{
// 临时禁用掉IMultiTenant过滤器
using (_dataFilter.Disable<IMultiTenant>())
{
var query = (await _repository.GetQueryableAsync()).WhereIf(!string.IsNullOrWhiteSpace(input.Filter), a => a.Title.Contains(input.Filter));
var totalCount = await query.CountAsync();
var items = await query.OrderBy(input.Sorting ?? "Id").Skip(input.SkipCount).Take(input.MaxResultCount).ToListAsync();
var dto = ObjectMapper.Map<List<Article>, List<ArticleDto>>(items);
return new PagedResultDto<ArticleDto>(totalCount, dto);
}
}
对于"主中心中可以看到所有分中心的User数据"这个问题,因为只是涉及到查看,不做增删改,所以又新建了一个User查找接口,在该接口中直接IDataFilter局部过滤。这样新建的User查找接口就可以看到所有分中心的数据,原来的User查找接口仅能看到宿主或者租户的User数据。总之,适合自己需求的架构就是最好的,如果架构满足不了需求了,那么就迭代架构。
参考文献: [1]数据过滤:https://docs.abp.io/zh-Hans/abp/6.0/Data-Filtering [2]Volo.Abp.Data:https://github.com/abpframework/abp/tree/dev/framework/src/Volo.Abp.Data [3]EntityFramework.DynamicFilters:https://github.com/zzzprojects/EntityFramework.DynamicFilters [4]ABP文档笔记 - 数据过滤:https://www.cnblogs.com/wj033/p/6494879.html [5]ABP领域层 - 数据过滤器:https://www.kancloud.cn/gaotang/abp/225839 [6]Mastering-ABP-Framework:https://github.com/PacktPublishing/Mastering-ABP-Framework [7]ABP多租户:https://docs.abp.io/zh-Hans/abp/6.0/Multi-Tenancy [8]ASP.NET Boilerplate中文文档:https://www.kancloud.cn/gaotang/abp/225819 [9]详解ABP框架中数据过滤器与数据传输对象使用:https://wenku.baidu.com/view/ec237e90b3717fd5360cba1aa8114431b80d8e5e [10]ASP.NET Boilerplate官方文档:https://aspnetboilerplate.com/Pages/Documents/Introduction [11]How to create a custom data filter with EF Core:https://support.aspnetzero.com/QA/Questions/4752/How-to-create-a-custom-data-filter-with-EF-Core
转载来源: https://www.cnblogs.com/shengshengwang/p/16564270.html
边栏推荐
- 新起之秀 DPU,正在掀起数据中心变革!
- The FFmpeg library is configured and used on win10 (libx264 is not configured)
- 国产抗新冠口服药每瓶不超300元/ 我国IPv6网络全面建成/ 谷歌入局折叠屏手机...今日更多新鲜事在此...
- WeChat payment development process
- 使用注解将EventBus封装抽取到基类
- 两分钟录音就可秒变语言通!火山语音音色复刻技术如何修炼而成?
- Too much volume... Tencent was asked on the side that the memory was full, what would happen?
- Say goodbye to the AI era of hand looms
- 26. Pipeline parameter substitution command xargs
- 无需精子卵子子宫体外培育胚胎,Cell论文作者这番话让网友们炸了
猜你喜欢
【无标题】
How to save Simulink simulation model as image or PDF
Here comes the question: Can I successfully apply for 8G memory on a machine with 4GB physical memory?
国产抗新冠口服药每瓶不超300元/ 我国IPv6网络全面建成/ 谷歌入局折叠屏手机...今日更多新鲜事在此...
win10编译x264库(也有生成好的lib文件)
2022牛客多校(六)M. Z-Game on grid
链表噩梦之一?5000多字带你弄清它的来龙去脉
Intranet penetration tool ngrok usage tutorial
1小时直播招募令:行业大咖干货分享,企业报名开启丨量子位·视点
箭头函数和普通函数的常见区别
随机推荐
LeetCode #101. Symmetric Binary Tree
十分钟教会你如何使用VitePress搭建及部署个人博客站点
Flutter入门进阶之旅(五)Image Widget
Flutter入门进阶之旅(二)Hello Flutter
西湖大学教授怎么看AI制药革命?|量子位智库圆桌实录
ABAP interview questions: how to use the System CALL interface of the ABAP programming language, direct execution ABAP server operating System's shell command?
FFmpeg在win10上编译安装(配置libx264)
Rust从入门到精通04-数据类型
中科院打脸谷歌:普通电脑追上量子优越性,几小时搞定原本要一万年的计算...
The batch size does not have to be a power of 2!The latest conclusions of senior ML scholars
生成上传密钥和密钥库
World's 4th mad scientist dies on his 103rd birthday
The core key points of microservice architecture
WeChat Mini Program Payment and Refund Overall Process
【HCIP持续更新】IS-IS协议原理与配置
罗振宇折戟创业板/ B站回应HR称用户是Loser/ 腾讯罗技年内合推云游戏掌机...今日更多新鲜事在此...
go基础之web获取参数
大佬们,请教一下,我看官方文档中,sqlserver cdc只支持2012版之后的,对于sqlser
Blocking, non-blocking, multiplexing, synchronous, asynchronous, BIO, NIO, AIO all in one pot
Use RecyclerView to implement three-level collapsed list