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