扩展EF的Fluent API中的 OnModelCreating方法 实现全局数据过滤器

1.生成过滤的表达式目录树

        protected virtual Expressionbool>> CreateFilterExpression()
            where TEntity : class
        {
            //构建的表达式目录树  TEntity就是满足条件的每个实体表
            Expressionbool>> expression = null;

            //根据租户ID进行过滤数据
            //expression = e => ((ILonsidEntity)e).TenantId == LonsidSession.TenantId;

            // TEntity类型是否继承ISoftDelete
            if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
            {
                //过滤出所有没有被软删除的记录
                Expressionbool>> softDeleteFilter = e => !((ISoftDelete)e).IsDeleted;
                //如果当前表达式为Null 就赋值      如果不为null  就把两个表达式组合
                expression = expression == null ? softDeleteFilter : CombineExpressions(expression, softDeleteFilter);
            }

            if (typeof(IMayHaveTenant).IsAssignableFrom(typeof(TEntity)))
            {
                /* This condition should normally be defined as below:
                 * !IsMayHaveTenantFilterEnabled || ((IMayHaveTenant)e).TenantId == CurrentTenantId
                 * But this causes a problem with EF Core (see https://github.com/aspnet/EntityFrameworkCore/issues/9502)
                 * So, we made a workaround to make it working. It works same as above.
                 */
                Expressionbool>> mayHaveTenantFilter = e => ((IMayHaveTenant)e).TenantId == CurrentTenantId || (((IMayHaveTenant)e).TenantId == CurrentTenantId) == IsMayHaveTenantFilterEnabled;
                expression = expression == null ? mayHaveTenantFilter : CombineExpressions(expression, mayHaveTenantFilter);
            }

            if (typeof(IMustHaveTenant).IsAssignableFrom(typeof(TEntity)))
            {
                /* This condition should normally be defined as below:
                 * !IsMustHaveTenantFilterEnabled || ((IMustHaveTenant)e).TenantId == CurrentTenantId
                 * But this causes a problem with EF Core (see https://github.com/aspnet/EntityFrameworkCore/issues/9502)
                 * So, we made a workaround to make it working. It works same as above.
                 */
                Expressionbool>> mustHaveTenantFilter = e => ((IMustHaveTenant)e).TenantId == CurrentTenantId || (((IMustHaveTenant)e).TenantId == CurrentTenantId) == IsMustHaveTenantFilterEnabled;
                expression = expression == null ? mustHaveTenantFilter : CombineExpressions(expression, mustHaveTenantFilter);
            }

            return expression;
        }

2.配置全局过滤器   将表达式目录树添加进来

        private void ConfigureFilters(ModelBuilder modelBuilder, IMutableEntityType entityType)
            where TEntity : class, ILonsidEntity
        {
            //entityType是否继承了ILonsidEntity   
            //这里应该不用这个判断 泛型 TEntity 已经有了约束条件 继承了ILonsidEntity
            if (typeof(ILonsidEntity).IsAssignableFrom(entityType.ClrType))
            {
                //创建过滤的表达式目录树
                var filterExpression = CreateFilterExpression();
                if (filterExpression != null)
                {
                    //将表达式引用到当前实体的任何查询中
                    modelBuilder.Entity().HasQueryFilter(filterExpression);
                }
            }
        }

3.获取过滤方法

        //通过反射获取当前DbConText中的  配置的全局过滤器方法    这个过滤方法是私有的    要加BindingFlags.NonPublic
        private static MethodInfo ConfigureFiltersMethodInfo = typeof(IMSDbContext).GetMethod(nameof(ConfigureFilters), BindingFlags.Instance | BindingFlags.NonPublic);

4.CRUD的时候执行过滤操作

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //先调用父类的方法
            base.OnModelCreating(modelBuilder);
            foreach (var entityType in modelBuilder.Model.GetEntityTypes())
            {
                //所有继承ILonsidEntity的实体类都需要添加自定义的全局过滤器
                if (typeof(ILonsidEntity).IsAssignableFrom(entityType.ClrType))
                {
                    ConfigureFiltersMethodInfo
                        .MakeGenericMethod(entityType.ClrType)
                        .Invoke(this, new object[] { modelBuilder, entityType });
                }
            }
        }

 *************************************

动态是否使用租户进行过滤的写法

                Expressionbool>> mayHaveTenantFilter = e => ((IMayHaveTenant)e).TenantId == CurrentTenantId || (((IMayHaveTenant)e).TenantId == CurrentTenantId) == IsMayHaveTenantFilterEnabled;

  

((IMayHaveTenant)e).TenantId == CurrentTenantId 前半句已经固定好了  一定会进行过滤租户      

关于后半句IsMayHaveTenantFilterEnabled默认为true 开启租户过滤
(((IMayHaveTenant)e).TenantId == CurrentTenantId) == IsMayHaveTenantFilterEnabled;
1. 如果IsMayHaveTenantFilterEnabled为true 开启过滤
当前数据库中的行满足(((IMayHaveTenant)e).TenantId == CurrentTenantId) 为true 后半句就为true
                                     为false 后半句就为false
  前半句跟后半句的真假性相同  只有租户相等的才会查询出来

2.如果IsMayHaveTenantFilterEnabled为false 禁用过滤
  当前数据库中的行满足(((IMayHaveTenant)e).TenantId == CurrentTenantId) 会给查询出来
  当前数据库中的行不满足(((IMayHaveTenant)e).TenantId == CurrentTenantId) 表达式查询条件变成 false || false == false 后半句永远为true 所以不会进行数据过滤

结论:
IsMayHaveTenantFilterEnabled 为 true  表达式 前半句跟后半句真假性相同  只查询数据行满足租户ID
IsMayHaveTenantFilterEnabled 为false  表达式 前半句跟后半句真假性相反  所有数据库行都满足这个where 条件





转载于:https://www.cnblogs.com/jiangchengbiao/p/10213773.html

你可能感兴趣的:(扩展EF的Fluent API中的 OnModelCreating方法 实现全局数据过滤器)