ABP中的數據過濾器

??本文首先介紹了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.cs4398c7d317a45bf1acd88fca9be5c1a0.png看了源碼實現后會發現格式一模一樣,所以自定義過濾器使用起來沒有這么復雜。

三.遇到的實際問題

??假如在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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/283876.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/283876.shtml
英文地址,請注明出處:http://en.pswp.cn/news/283876.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ActiveMQ與spring整合

2019獨角獸企業重金招聘Python工程師標準>>> 1 生產者 第一步&#xff1a;引用相關的jar包。 <dependency> <groupId>org.springframework</groupId><artifactId>spring-jms</artifactId> </dependency> <dependency><…

最新遠程部署運維工具匯總

一&#xff0e;Puppet 轉載https://baike.baidu.com/item/puppet/5109503?fraladdin puppet是一種Linux、Unix、windows平臺的集中配置管理系統&#xff0c;使用自有的puppet描述語言&#xff0c;可管理配置文件、用戶、cron任務、軟件包、系統服務等。puppet把這些系統實體…

Kali Linux 2016.2初體驗使用總結

Kali Linux 2016.2初體驗使用總結Kali Linux官方于8月30日發布Kali Linux 2016的第二個版本Kali Linux 2016.2。該版本距離Kali Linux 2016.1版本發布&#xff0c;已經有7個月。在這期間&#xff0c;在Kali Linux 2016.2版本發布的這段時間&#xff0c;Kali Linux官方增補了94個…

Kafka入門教程:學習總結目錄索引

【Kafka】| 總結/Edison ZhouEdison總結了Kafka的學習征途系列&#xff0c;特意整理了一份目錄索引&#xff0c;希望對你有幫助。0Kafka學習路徑在學習Kafka的途中&#xff0c;我總結了一個系列的Kafka學習征途系列教程&#xff0c;它只選取了我認為最實用的部分整理出來&#…

javaweb學習中的路徑問題

1. 項目結構 2. 客戶端路徑 1. 超鏈接 <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/…

步步為營-11-ListT泛型的簡單練習

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace 集合簡單練習 {class Program{static void Main(string[] args){}private static void Test3(){//奇偶分揀,奇數在前偶數在后List<int>…

SPI 與 API的區別

背景 Java 中區分 API 和 SPI&#xff0c;通俗的講&#xff1a;API 和 SPI 都是相對的概念&#xff0c;他們的差別只在語義上&#xff0c;API 直接被應用開發人員使用&#xff0c;SPI 被框架擴展人員使用 理解 API &#xff08;Application Programming Interface&#xff09; …

JS---------正則表達式

2019獨角獸企業重金招聘Python工程師標準>>> 1.正則表達式的創建方式&#xff1a; 1.1 var reg new RegExp(pattern); 1.2 var reg /^正則規則$/ 2.正則規則&#xff1a; 2.1 [0-9] 代表數字 [A-Z] 代表大寫字母 [a-z] 代表小寫字母 [A-z] 代表字母 \w 查找單詞字…

關于緩存異常:緩存雪崩、擊穿、穿透的解決方案

關于緩存雪崩、擊穿、穿透的解決方案 前言緩存雪崩 緩存雪崩的原因解決方案緩存擊穿 解決方案緩存穿透 解決方案 布隆過濾器 布隆過濾器原理布隆過濾器如何使用在Java中使用布隆過濾器前言 關于緩存異常&#xff0c;我們常見的有三個問題&#xff1a;緩存雪崩、緩存擊穿、緩存穿…

RobotFramework 自動化測試實戰進階篇

工具 Robotframework, 采用PO設計模式 PO模型 PO模型即Page Objects&#xff0c;直譯意思就是“頁面對象”&#xff0c;通俗的講就是把一個頁面&#xff0c;或者說把一個頁面的某個區域當做一個對象&#xff0c;通過封裝這個對象可以實現調用。 PO設計的好處 代碼復用&…

Android6 0權限機制(一):介紹

本篇文章已授權微信公眾號 hongyangAndroid &#xff08;鴻洋&#xff09;獨家發布 Android6.0權限機制&#xff08;一&#xff09;&#xff1a;介紹 Android6.0權限機制&#xff08;二&#xff09;&#xff1a;封裝 Android6.0權限機制&#xff08;三&#xff09;&#xff1a;…

MAX10 ADC的一些基知識

MAX10 ADC 的一些知識 1、 MAX 10 內部集成的12bit SAR ADC的特點為&#xff1a; a、 采樣速率高達1Mhz. b、 模擬通道多達18個&#xff0c;單個ADC多達17個&#xff0c;雙ADC器件中有16個雙功能ADC通道&#xff0c;2個專用的ADC。 c、 提供單端測…

Blazor University (42)JavaScript 互操作 —— 生命周期和內存泄漏

原文鏈接&#xff1a;https://blazor-university.com/javascript-interop/calling-dotnet-from-javascript/lifetimes-and-memory-leaks/生命周期和內存泄漏源代碼[1]如果我們運行我們在從 Javascript 調用 .NET 中創建的應用程序并檢查瀏覽器控制臺窗口&#xff0c;我們會看到…

深入淺出聊布隆過濾器(Bloom Filter)

之前在網上看到過這么一段話&#x1f447; Data structures are nothing different. They are like the bookshelves of your application where you can organize your data. Different data structures will give you different facility and benefits. To properly use the …

第五周作業

本周作業內容&#xff1a;顯示當前系統上root、fedora或user1用戶的默認shell&#xff1b;#egrep "^(root|user1|fedora)" /etc/passwd|cut -d: -f72、找出/etc/rc.d/init.d/functions文件中某單詞后面跟一組小括號的行&#xff0c;形如&#xff1a;hello()&#xff…

我為什么卸載了今日頭條

曾經的自媒體人自述。 兩三年前自媒體熱曾席卷中國互聯網&#xff0c;當時短視頻還不是很火&#xff0c;一般的自媒體人都是以撰寫文章為主&#xff0c;各種微信公眾號層出不窮&#xff0c;10W的俗稱 爆文&#xff08;豹紋&#xff09;。后來以今日頭條為領頭的短視頻自媒體出現…

appium執行iOS測試腳本并發問題

appium1.4.XiOS9.Xxcode7.X: appium1.4.xiOS9.xxcode7.x&#xff0c;這一整套的配置做移動端自動化測試是測試人員常用的測試框架。關于&#xff0c;這一套測試框架的并發問題&#xff1a;基于mac端&#xff0c;啟動多臺appium服務器會導致appium的運行出錯。這是因為多個appiu…

WinForm(五)控件和它的成員

窗體無疑是WinForm的主角&#xff0c;每個窗體都是用一個class來承載&#xff0c;那么窗體的控件&#xff0c;就是類中的私有字段了。每個窗體有三個文件&#xff0c;兩個.cs文件&#xff0c;是一個分部類&#xff0c;Designer.cs是自動生成的C#代碼&#xff0c;一般是拖拽控件…

Atitit.異常處理 嵌套??冗長的解決方案

Atitit.異常處理 嵌套 冗長的解決方案 1. 異常處理的需要改進的地方1 2. 異常設計的初衷是, 在程序中出現錯誤時, 由程序自己處理錯誤, 盡量不要以exit(0)這種粗暴的方式中止程序. 1 3. 正常流程和異常流程的分離。2 4. “是藥三分毒”&#xff0c; 任何事物有缺點&#xff0c…

一文詳解|增長那些事兒

目錄 增長的背景 1.1 增長的定義 1.2 如何判斷事物是否在增長 1.3 如何判斷事物能否持續增長 如何進行增長 2.1 尋找增長機會點&#xff08;人的能力&#xff09; 2.1.1 發散與收劍找機會點 2.1.2 實驗分析驗證 2.1.3 增長洞察提取策略 2.1.4 如何找到大機會 2.2 設…