ABP 配置全局数据过滤器
可以不看下面内容,直接看这:https://www.cnblogs.com/MindSharing/p/11283914.html
================================
ABP官方数据过滤的地址:https://aspnetboilerplate.com/Pages/Documents/Data-Filters
中文可以看这个:https://aspnetboilerplate.com/Pages/Documents/Data-Filters
看完后最大问题就是,自定义的数据过滤和UOW中事务是在一起的
using (CurrentUnitOfWork.EnableFilter("PersonFilter")) { using(CurrentUnitOfWork.SetFilterParameter("PersonFilter", "personId", 42)) { var phones = _phoneRepository.GetAllList(); //... } }
总不可能每次我写服务的时候,都在方法里面写一串这个代码吧,那这样也没方便多少
所以可以考虑使用我方法来给过滤器全局设置一个值。
我的应用场景是这样的,我的项目登录的时候会让用户选择一个专业,所有数据都是这个专业下的,什么建筑啊,结构啊
为了实现这个筛选,先还是需要建立过滤器,在Core项目添加一个接口
public interface IHasMajor { string Major { get; set; } }
在EF项目中的DbContext.cs 中注册 过滤器
protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Filter("MajorFilter", (IHasMajor entity, string major) => entity.Major == major, ""); }
在你需要筛选专业的实体里面实现这个接口
[Table("DictionaryInfo")] public class DictionaryInfo : FullAuditedEntity, IHasMajor { public virtual int? ParentId { get; set; } public virtual string Value { get; set; } public virtual string Description { get; set; } public virtual DictionaryInfo ParentDictionaryInfo { get; set; } public virtual ICollection<DictionaryInfo> ChildDictionaryInfos { get; set; } public virtual string Major { get; set; } }
好了下面就是关键的了,传统做法,我们就是在服务里面设置数据过滤的参数
public async Task<GetDictionaryInfoOutput> GetAllDictionary() { using (CurrentUnitOfWork.SetFilterParameter(SysConsts.DataFilter.MajorFilter, SysConsts.DataFilter.MajorParameter, AbpSession.GetMajor())) { List<DictionaryInfo> dictionaries = await _dictionaryInfoRepository.GetAllListAsync(); var result = new GetDictionaryInfoOutput { Dictionary = dictionaries.MapTo<List<DictionaryInfoDto>>() }; return result; } }
这种方式感觉很不优雅,改用拦截器来自动为每个服务注入 过滤器参数,
ABP 官方对拦截器他也给了个例子,可以看这个
https://www.codeproject.com/Articles/1080517/Aspect-Oriented-Programming-using-Interceptors-wit
添加个一个拦截器,在应用层
public class FilterInterceptor : IInterceptor { private readonly IAbpSession _abpSession; private readonly IUnitOfWork _unitOfWork; private readonly IUnitOfWorkManager _unitOfWorkManager; public FilterInterceptor( IUnitOfWork unitOfWork , IAbpSession abpSession , IUnitOfWorkManager unitOfWorkManager) { Logger = NullLogger.Instance; _unitOfWork = unitOfWork; _abpSession = abpSession; _unitOfWorkManager = unitOfWorkManager; } public ILogger Logger { get; set; } public void Intercept(IInvocation invocation) { string major = _abpSession.GetMajor(); _unitOfWorkManager.Current.SetFilterParameter(SysConsts.DataFilter.MajorFilter, SysConsts.DataFilter.MajorParameter, major); //Executing the actual method invocation.Proceed(); } }
这里面有一个主意地方,拦截器请注入IUnitOfWorkManager ,而不是注入IUnitOfWork ,后者设置参数了,没效果
然后再注册拦截器,在应用层添加一个文件
public static class InterceptorRegistrar { public static void Initialize(IKernel kernel) { kernel.ComponentRegistered += Kernel_ComponentRegistered; } private static void Kernel_ComponentRegistered(string key, IHandler handler) { if (typeof(IApplicationService).IsAssignableFrom(handler.ComponentModel.Implementation)) { handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(FilterInterceptor))); } } }
在应用层的ApplicationModule.cs 文件里面的PreInitialize方法里面
public override void PreInitialize() { InterceptorRegistrar.Initialize(IocManager.IocContainer.Kernel); }
好这样就注册完了,可以试试服务层每个方法都能自动判断专业了,把服务里面手动设置筛选参数的地方都可以去掉了
public async Task<GetDictionaryInfoOutput> GetAllDictionary() { //using (CurrentUnitOfWork.SetFilterParameter(SysConsts.DataFilter.MajorFilter, SysConsts.DataFilter.MajorParameter, AbpSession.GetMajor())) //{ List<DictionaryInfo> dictionaries = await _dictionaryInfoRepository.GetAllListAsync(); var result = new GetDictionaryInfoOutput { Dictionary = dictionaries.MapTo<List<DictionaryInfoDto>>() }; return result; //} }
专业的值是存在session里面的,如何把自己想要的值存到session 里面,可以参照这篇文章
http://www.jianshu.com/p/930c10287e2a