当前位置:网站首页>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
边栏推荐
- 两个链表相加
- Ten minutes to teach you how to use VitePress to build and deploy a personal blog site
- Scala 高阶(七):集合内容汇总(上篇)
- 世界第4疯狂的科学家,在103岁生日那天去世了
- Resolved IndentationError: unindent does not match any oute r indentation Level
- 腾讯发布第二代四足机器人Max,梅花桩上完成跳跃、空翻
- ansible-cmdb friendly display ansible collects host information
- The core key points of microservice architecture
- How to upload local file trial version in binary mode in ABAP report
- 微服务架构的核心关键点
猜你喜欢
一甲子,正青春,CCF创建六十周年庆典在苏州举行
新起之秀 DPU,正在掀起数据中心变革!
张朝阳对话俞敏洪:一边是手推物理公式,一边是古诗信手拈来
ABAP 面试题:如何使用 ABAP 编程语言的 System CALL 接口,直接执行 ABAP 服务器所在操作系统的 shell 命令?
win10编译x264库(也有生成好的lib文件)
Say goodbye to the AI era of hand looms
Compensation transaction and idempotency guarantee based on CAP components
保存Simulink仿真模型为图片或者PDF的方法
Scala 高阶(七):集合内容汇总(上篇)
Manchester city launch emotional intelligence scarf can be detected, give the fans
随机推荐
Intranet penetration tool ngrok usage tutorial
数字化转型之支撑保障单元
AI篮球裁判火了,走步算得特别准,就问哈登慌不慌
Compensation transaction and idempotency guarantee based on CAP components
Say goodbye to the AI era of hand looms
The core key points of microservice architecture
已解决IndentationError: unindent does not match any oute r indentation Level
ansible-cmdb友好展示ansible收集主机信息
MySQL5.6到8.0的账号迁移
The latest interview summary in 20022 brought by Ali senior engineer is too fragrant
900页数学论文证明旋转的黑洞不会爆炸,丘成桐:30多年来广义相对论首次重大突破...
数据挖掘-05
Flutter入门进阶之旅(六)Layout Widget
放下手机吧:实验表明花20分钟思考和上网冲浪同样快乐
World's 4th mad scientist dies on his 103rd birthday
二叉树的序列化和反序列化
张朝阳对话俞敏洪:一边是手推物理公式,一边是古诗信手拈来
WeChat side: what is consistent hashing, usage scenarios, and what problems does it solve?
基于CAP组件实现补偿事务与幂等性保障
微服务架构的核心关键点