ef core提供了Global Query Filters特性来实现多租户与软删除,收集了一些实现方法。

最简单的例子是微软官方的特性解释。

https://docs.microsoft.com/en-us/ef/core/querying/filters

 modelBuilder.Entity<Post>().HasQueryFilter(p => !p.IsDeleted);

比较全面的实现可参考:

https://gunnarpeipman.com/ef-core-global-query-filters/

需要注意Cache问题:

https://docs.microsoft.com/en-us/ef/core/modeling/dynamic-model

https://spin.atomicobject.com/2019/01/29/entity-framework-core-soft-delete/

https://www.meziantou.net/entity-framework-core-soft-delete-using-query-filters.htm

https://comment-it.co.uk/entity-framework-core-soft-delete-workaround/

其中如果需要扫描model自动注册所有实体,属于是高阶用法

构建Expression的代码难以理解,不便后人维护,不过学习一下对理解lambda表达式的底层还是有帮助的

// 1. Add the IsDeleted property
entityType.GetOrAddProperty("IsDeleted", typeof(bool)); // 2. Create the query filter var parameter = Expression.Parameter(entityType.ClrType); // EF.Property<bool>(post, "IsDeleted")
var propertyMethodInfo = typeof(EF).GetMethod("Property").MakeGenericMethod(typeof(bool));
var isDeletedProperty = Expression.Call(propertyMethodInfo, parameter, Expression.Constant("IsDeleted")); // EF.Property<bool>(post, "IsDeleted") == false
BinaryExpression compareExpression = Expression.MakeBinary(ExpressionType.Equal, isDeletedProperty, Expression.Constant(false)); // post => EF.Property<bool>(post, "IsDeleted") == false
var lambda = Expression.Lambda(compareExpression, parameter); builder.Entity(entityType.ClrType).HasQueryFilter(lambda);

lambda通过全局函数借助统一的父类实现,当然实际开发中,可以改为接口扫描来做。需要注意多个filter条件需要通过“与”操作一起设置,否则后面设置会覆盖前面的设置。

public void SetGlobalQuery<T>(ModelBuilder builder) where T : BaseEntity
{
builder.Entity<T>().HasKey(e => e.Id);
builder.Entity<T>().HasQueryFilter(e => e.TenantId == _tenant.Id);
}
private static IList<Type> GetEntityTypes()
{
if (_entityTypeCache != null)
{
return _entityTypeCache.ToList();
} _entityTypeCache = (from a in GetReferencingAssemblies()
from t in a.DefinedTypes
where t.BaseType == typeof(BaseEntity)
select t.AsType()).ToList(); return _entityTypeCache;
}
protected override void OnModelCreating(ModelBuilder builder)
{
var navigation = builder.Entity<ProductCategory>()
.Metadata
.FindNavigation(nameof(ProductCategory.Products)); navigation.SetPropertyAccessMode(PropertyAccessMode.Field); foreach (var type in GetEntityTypes())
{
var method = SetGlobalQueryMethod.MakeGenericMethod(type);
method.Invoke(this, new object[] { builder });
} base.OnModelCreating(builder);
}

ef core SoftDelete Multi-tenancy 软删除、多租户实现 Global Query Filters的更多相关文章

  1. ef core实现无感知软删除

    很多web程序一般的偶不会设计真的物理删除了. 基本上都是在在数据库加一个标记,就得当作已经删除了.同时在查询的时候,过滤已经标记删除的数据 ef core实现软删除是非常简单的,直接在OnModel ...

  2. EntityFramework.DynamicFilters 实现软删除和租户过滤

    EntityFramework.DynamicFilters 实现软删除和租户过滤

  3. EF Core中Fluent Api如何删除指定数据表中的行

    这两天一直在研究在code first下如何删除数据表中的指定行,于是开始搜狗,后来百度,压根就找不到资料,后来一想可能我的搜索关键字有问题,而且ef core命令与ef的命令差不多,于是从这两个方面 ...

  4. 深入理解 EF Core:使用查询过滤器实现数据软删除

    原文:https://bit.ly/2Cy3J5f 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能会去除一些本人实在不知道如何组织 ...

  5. 【EF】Entity Framework Core 软删除与查询过滤器

    本文翻译自<Entity Framework Core: Soft Delete using Query Filters>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 注意 ...

  6. EF Core 实现多租户

    目录 SAAS 和多租户 多租户数据隔离方案 使用 EF Core 简单实现多租户 单数据库实现 多数据库实现 源代码 参考 SAAS 和多租户 SaaS(软件及服务)区别于其他应用程序的主要特征就是 ...

  7. 深入理解 EF Core:EF Core 写入数据时发生了什么?

    阅读本文大概需要 14 分钟. 原文:https://bit.ly/2C67m1C 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能 ...

  8. EF core 性能调优

    Entity Framework Core performance tuning – a worked example Last Updated: February 25, 2019 | Create ...

  9. DDD Code First 迁移数据实现EF CORE的软删除,值对象迁移配置

    感谢Jeffcky大佬的博客: EntityFramework Core 2.0全局过滤 (HasQueryFilter) https://www.cnblogs.com/CreateMyself/p ...

随机推荐

  1. IT兄弟连 HTML5教程 HTML5表单 HTML5新增表单元素

    HTML5有一些新的表单元素:<datalist>.<keygen>.<output>.不是所有的浏览器都支持HTML5新的表单元素,但即使浏览器不支持该表单属性, ...

  2. Centos6进入单用户模式的两种方法

    单用户模式的作用 在使用Linux系统中,维护人员经常会碰到一个问题,就是在拥有root账号权限和密码的用户中,总是会出现忘记root密码的情况.遇到这种情况,一般情况下,维护人员就会通过最常用的方法 ...

  3. JS如何判断鼠标滚轮向上还是向下滚动

    前几天偶然看到某前端群有人在问:JS如何判断鼠标滚轮向上还是向下滚动? 我想了想,有点蒙蔽,心想难道不是用scrollTop来判断吗? 但我不确定,也出于好奇心,于是开始了一番探索 思路:通过even ...

  4. 手把手教你搭建织女星开发板RISC-V开发环境

    前言 Windows环境下搭建基于Eclipse + RISC-V gcc编译器的RISC-V开发环境,配合openocd调试软件,可以实现RISC-V内核程序的编译.下载和调试. 准备工作 工欲善其 ...

  5. PAT 1007 Maximum Subsequence Sum 最大连续子序列和

    Given a sequence of K integers { N1, N2, …, NK }. A continuous subsequence is defined to be { Ni, Ni ...

  6. 【nodejs原理&源码杂记(8)】Timer模块与基于二叉堆的定时器

    目录 一.概述 二. 数据结构 2.1 链表 2.2 二叉堆 三. 从setTimeout理解Timer模块源码 3.1 timers.js中的定义 3.2 Timeout类定义 3.3 active ...

  7. SSL/TLS 链接的建立/握手

    HTTPS 即 HTTP-within-SSL/TLS,其中 SSL/TLS 又分别表示: SSL:Secure Sockets Layer TLS:Transport Layer Security ...

  8. 松软科技web课堂:SQLServer之HAVING 子句

    HAVING 子句 在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与合计函数一起使用. SQL HAVING 语法 SELECT column_name, aggregate_f ...

  9. JS关于日期格式转换的问题

    写Js时,有个地方用到日期,要求是yyyy--MM--dd的格式,于是想到了format函数,下面介绍了时间函数的定义,和调用前引入函数和如何格式化自己想要的日期格式. //当前时间 var Time ...

  10. mysql8之坑

    一.具体"坑" 1.修改密码和修改加密方式 mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码' PASSWORD ...