当前位置: 首页 > article >正文

PasteForm(ABP)框架之实现更加灵活的类似多租户的归属过滤功能,比如只能查看自己的相关数据

需求说明

在开发中,我们常会遇到一个问题,就是归属查询问题,比如只能查看我自己的,往往这个时候还附带了一个规则,比如有人是在这个规则之外的!
1.只能查看创建者自己创建的资料
2.只能查看我店铺的相关内容,不能查看别人店铺的
3.只能查看我部门的相关信息等

可能你会说,直接查询的时候加条件即可!道理就是这么个道理,哪怕是多租户其实也是这样实现的!

** 为啥不直接用多租户呢 **

多租户在我的项目中,用得非常非常少,更多的用的是灵活的协作模式,比如多店铺模式,多商户号模式等!

1.目前的多租户限制比较多,如果引入了,变成店铺+多租户,多了一层关系,别和我说扩展,我感觉扩展还是不如重写来得直接!
2.很多查询,其实并不是严格的多租户模式,比如有些组织,或者个人拥有多个店铺太正常了
3.范围限定,你不能多租户套多租户吧,但是实际需求中往往很多限定的,比如只能查看他自己创建的东西,外面又套了一层店铺

案例分析

在PasteDocument项目中,有这么一个需求,我只能查看我组织的信息,为啥我没用多租户做呢,当时也是考虑使用多租户的,后面放弃了,我宁愿每个表都加一个字段CompanyId

1.Company本身,我有很多自定义的规则
2.多租户用的是Guid,实际中给我的感觉数据库如果没有必要还是不要使用Guid作为主键的好,其实int/long完全够用,当然Guid也有他的优点所在,比如别人猜不到你的日增长,至于说基于id猜数据的,我只能说是你的权限有问题,而不是数据本身!
3.不够灵活,因为我一个用户率属于多个组织太正常了
4.后续扩展考虑

综上,你看需求不就来了么,好了,直接上代码!

解决思路

居然有多租户这个模式,那直接按照他的思路来改即可,对吧!

解读当前方案

下载ABP的源码后,我们在AbpDbContext中看到如下代码,主要是针对多租户的

    protected virtual Expression<Func<TEntity, bool>>? CreateFilterExpression<TEntity>()where TEntity : class{Expression<Func<TEntity, bool>>? expression = null;if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))){expression = e => !IsSoftDeleteFilterEnabled || !EF.Property<bool>(e, "IsDeleted");}if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity))){Expression<Func<TEntity, bool>> multiTenantFilter = e => !IsMultiTenantFilterEnabled || EF.Property<Guid>(e, "TenantId") == CurrentTenantId;expression = expression == null ? multiTenantFilter : QueryFilterExpressionHelper.CombineExpressions(expression, multiTenantFilter);}return expression;}

注意看上面的2个被引用的参数
IsMultiTenantFilterEnabled:是否需要过滤多租户
CurrentTenantId:当前的多租户是多少
然后上面的函数意思是基于2个变量生成一个表达式!
看看谁调用他了

    protected virtual void ConfigureGlobalFilters<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType)where TEntity : class{if (mutableEntityType.BaseType == null && ShouldFilterEntity<TEntity>(mutableEntityType)){var filterExpression = CreateFilterExpression<TEntity>();if (filterExpression != null){var abc = modelBuilder.Entity<TEntity>();modelBuilder.Entity<TEntity>().HasAbpQueryFilter(filterExpression);}}}

感觉可以略过,意思就是判断Entity是否继承于设定的IMultiTenant

    protected virtual bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType) where TEntity : class{if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity))){return true;}if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))){return true;}return false;}

我们再看看ConfigureGlobalFilters被谁调用了

    protected virtual void ConfigureBaseProperties<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType)where TEntity : class{if (mutableEntityType.IsOwned()){return;}if (!typeof(IEntity).IsAssignableFrom(typeof(TEntity))){return;}modelBuilder.Entity<TEntity>().ConfigureByConvention();ConfigureGlobalFilters<TEntity>(modelBuilder, mutableEntityType);}

这个判断,啥意思?防止自己调用自己?那估计是有递归查之类的,别管,继续上一级

    private static readonly MethodInfo ConfigureBasePropertiesMethodInfo= typeof(AbpDbContext<TDbContext>).GetMethod(
http://www.lryc.cn/news/2401623.html

相关文章:

  • 本地id_rsa.pub输入到服务器~/.ssh/authorized_keys后,依然需要输入密码的解决办法
  • 【设计模式-3.7】结构型——组合模式
  • Unity Mac 笔记本操作入门
  • 实时数据仓库是什么?数据仓库设计怎么做?
  • Linux(12)——基础IO(下)
  • WPF可拖拽ListView
  • rocketmq索引
  • [蓝桥杯]倍数问题
  • 定时任务的 cron 表达式
  • 【MySQL】 约束
  • MySQL 的 redo log 和 binlog 区别?
  • 前端vue打开多个窗口,关闭窗口后才继续执行后续逻辑
  • 「深度拆解」Spring Boot如何用DeepSeek重构MCP通信层?从线程模型到分布式推理的架构进化
  • 如何避免在前端项目中出现重复的第三方依赖包?
  • Java开发中复用公共SQL的方法
  • 【西门子杯工业嵌入式-2-点亮一颗LED】
  • 代码随想录算法训练营第60期第五十五天打卡
  • 重磅更新! 基于Gemini 2.5 Pro打造的AI智能体PlantUML-X上线!
  • [5-02-04].第01节:Jmeter环境搭建:
  • AI智能推荐实战之RunnableParallel并行链
  • windows server2019 不成功的部署docker经历
  • Gemini开源项目DeepResearch:基于LangGraph的智能研究代理技术原理与实现
  • React状态管理Context API + useReducer
  • 【无标题】路径着色问题的革命性重构:拓扑色动力学模型下的超越与升华
  • Doris Catalog 联邦分析查询性能优化:从排查到优化的完整指南
  • 01 Deep learning神经网络的编程基础 二分类--吴恩达
  • 视频自动化分割方案:支持按时间与段数拆分
  • Open SSL 3.0相关知识以及源码流程分析
  • 股指期货合约价值怎么算?
  • 【QT】使用QT帮助手册找控件样式