扩展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 条件
扩展EF的Fluent API中的 OnModelCreating方法 实现全局数据过滤器的更多相关文章
- Web Api中实现Http方法(Put,Post,Delete)
在Web Api中实现Http方法(Put,Post,Delete) 系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 在Web Api中,我 ...
- EF Core Fluent API
多对多配置 先安装 Install-Package MySql.Data.EntityFrameworkCore 创建3个表 创建类 public class Role { public long I ...
- 一步一步学EF系列1【Fluent API的方式来处理实体与数据表之间的映射关系】
EF里面的默认配置有两个方法,一个是用Data Annotations(在命名空间System.ComponentModel.DataAnnotations;),直接作用于类的属性上面,还有一个就是F ...
- 第六节:框架搭建之EF的Fluent Api模式的使用流程
一. 前言 沉寂了约一个月的时间,今天用一篇简单的文章重新回归博客,主要来探讨一下Fluent Api模式在实际项目中的使用流程. 1. Fluent API属于EF CodeFirst模式的一种,E ...
- 一步一步学EF系列二【Fluent API的方式来处理实体与数据表之间的映射关系】
EF里面的默认配置有两个方法,一个是用Data Annotations(在命名空间System.ComponentModel.DataAnnotations;),直接作用于类的属性上面,还有一个就是F ...
- 第十八篇 .NET高级技术之Linq与EF Code-First Fluent API基础讲解
1.FluentApi简介 在这里提供了一个fluentapi基础的DEMO然后咱们在进一步的学习,直接上干货. 第一步在数据库创建一个表:person 第二步:新建控制台程序FluentAPI 第三 ...
- EF:Fluent API 把一对多映射为一对一
假设有两张表:A表和B表.A表与B表在数据库中的关系是一对多,但我们需要在EF中映射为一对一. 首先在A实体类和B实体类中互相为对方增加一个实体类的属性: public A { public B B ...
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【五】——在Web Api中实现Http方法(Put,Post,Delete)
系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 在Web Api中,我们对资源的CRUD操作都是通过相应的Http方法来实现——Post(新 ...
- EF使用Fluent API配置映射关系
定义一个继承自EntityTypeConfiguration<>泛型类的类来定义domain中每个类的数据库配置,在这个自定义类的构造函数中使用我们上次提到的那些方法配置数据库的映射. 映 ...
随机推荐
- 第一节 JavaScript概述
第一节 JavaScript概述 JavaScript:其实就是对HTML+CSS静态页面进行样式修改,使其实现各种动态效果. 编写JS脚本基本步骤: 1. HTML+CSS静态布局: 2. 确定要修 ...
- Qt QTextEdit根据行号移动光标
QTextEdit* p = new QTextEdit; QTextBlock block = p->document()->findBlockByNumber(nLineNum); p ...
- linux shell习题
课件地址:https://wenku.baidu.com/view/bac2ff10f18583d0496459f3.html 1.测试环境变量:HOME,PWD,IFS等2.测试位置变量:$$,$# ...
- sqlchemy self made
# -*- coding: utf-8 -*- from sqlalchemy import create_engine, Column, String, Integer, ForeignKey, T ...
- django加载静态文件
在一个网页中,不仅仅只有一个 html 骨架,还需要 css 样式文件. js 执行文件以及一些图片等,因此在 DTL 中加载静态文件是一个必须要解决的问题.在 DTL 中,使用 static 标签来 ...
- powermock+mockito+testng 单元测试pom文件
0:Supported versions PowerMock version 1.7.0 and upper has experimental support of Mockito 2. A lot ...
- gdb调试程序函数名为问号,什么原因?step by step解决方案
gdb调试程序函数名为问号,什么原因? http://bbs.chinaunix.net/thread-1823649-1-1.html http://www.bubuko.com/infodetai ...
- metasploit(MSF)对windows的ms17-010漏洞利用
picture 配置exploit msf > use exploit/windows/smb/ms17_010_eternalblue msf exploit(windows/smb/ms17 ...
- Computer Study
2017.12.15日开始制定长期学习计划: 大二上: 目前短期计划: 1.每天一道PAT乙级(弄完PAT乙级)+校OJ(打基础). 2.先复习C++,17周后开始复习数据结构.(补任务 刚刚发 ...
- VC++使用MapFileAndCheckSum完成自检测
转载:https://blog.csdn.net/lekonpeng/article/details/4150464 当我们完成一个工程,编译成可执行文件后,一般是不希望这个可执行文件被人改动的,那么 ...