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(
                nameof(ConfigureBaseProperties
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贴代码科技-致力于开发更加适用的应用

要不请我喝杯咖啡!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值