zoukankan      html  css  js  c++  java
  • 扩展EF的Fluent API中的 OnModelCreating方法 实现全局数据过滤器

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

            protected virtual Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
                where TEntity : class
            {
                //构建的表达式目录树  TEntity就是满足条件的每个实体表
                Expression<Func<TEntity, bool>> expression = null;
    
                //根据租户ID进行过滤数据
                //expression = e => ((ILonsidEntity)e).TenantId == LonsidSession.TenantId;
    
                // TEntity类型是否继承ISoftDelete
                if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
                {
                    //过滤出所有没有被软删除的记录
                    Expression<Func<TEntity, bool>> 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.
                     */
                    Expression<Func<TEntity, bool>> 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.
                     */
                    Expression<Func<TEntity, bool>> mustHaveTenantFilter = e => ((IMustHaveTenant)e).TenantId == CurrentTenantId || (((IMustHaveTenant)e).TenantId == CurrentTenantId) == IsMustHaveTenantFilterEnabled;
                    expression = expression == null ? mustHaveTenantFilter : CombineExpressions(expression, mustHaveTenantFilter);
                }
    
                return expression;
            }

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

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

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

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

                    Expression<Func<TEntity, bool>> 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 条件





  • 相关阅读:
    iPhone控件之UIDatePicker
    iPhone控件之UIActionSheet
    iPhone控件之UIActivityView
    iPhone控件之UIPickerView2
    RTP/RTCP协议详解
    ASIHTTPRequest详解[转载]
    iPhone控件之UIProgressView
    iPhone控件之UIPageControl
    iPhone控件之UISegmentedControl
    使用AsyncSocket实现RTSP协议
  • 原文地址:https://www.cnblogs.com/jiangchengbiao/p/10213773.html
Copyright © 2011-2022 走看看