全局查询筛选器适用场景 以及各场景示例

EF Core中的全局查询筛选器(Global Query Filters)是一种强大的功能,可以在实体框架的DbContext级别为特定的EntityType设置默认的过滤条件。这些筛选器自动应用于所有涉及到相关实体的LINQ查询中,无论是直接查询还是通过Include或导航属性间接引用的情况。

以下是一些适用场景:

  • 多租户: 在多租户应用程序中,每个租户的数据应该彼此隔离。通过使用全局查询筛选器,可以轻松确保每次查询仅返回特定租户的数据,而无需在每个查询中显式添加Where子句。

  • **软删除:**软删除是一种数据管理策略,允许在数据库中保留已删除的数据,而不是完全从数据库中移除。通过使用全局查询筛选器,可以自动排除那些被标记为已删除的数据行,从而在查询结果中只包含未删除的数据。

  • 数据访问权限 :在某些应用中,您可能基于用户的角色或权限来限制他们可以访问的数据。全局查询筛选器可以确保即使忘记了添加权限检查,查询也仍然只返回用户可以访问的数据。


软删除

软删除是一种数据管理策略,它允许在数据库中保留已删除的数据,而不是完全从数据库中移除。这种策略通常通过添加一个布尔类型的列(如IsDeleted)来实现,该列标记着每行数据是否已被逻辑删除。

以下是一个示例

1.定义实体:首先,你需要定义包含特定属性的实体类,例如用于软删除的IsDeleted属性。

cs 复制代码
public class MyEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsDeleted { get; set; }
}
  1. 配置筛选器:接下来,在OnModelCreating方法中使用HasQueryFilter API为实体类型配置查询筛选器。这些筛选器以LINQ查询谓词的形式存在,并自动应用于所有相关的查询操作。
cs 复制代码
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyEntity>()
        .HasQueryFilter(e => !e.IsDeleted);
}
  1. 执行删除操作:当你需要删除一个实体时,只需将IsDeleted属性设置为true,而不是实际从数据库中删除它。
cs 复制代码
var entity = new MyEntity { Id = 1, Name = "Example" };
context.MyEntities.Add(entity);
await context.SaveChangesAsync();

entity.IsDeleted = true;
await context.SaveChangesAsync();

4.恢复删除的数据:如果你意外删除了数据,你可以轻易地通过更改IsDeleted标志来恢复。

cs 复制代码
entity.IsDeleted = false;
await context.SaveChangesAsync();

优缺点:

  • 优点

    • 恢复数据 :如果你意外删除了数据,你可以轻易地通过更改IsDeleted标志来恢复。
    • 审计和历史记录:保留了数据的历史记录,有助于进行审计和分析。
    • 提高性能:在某些情况下,软删除可以提高性能,因为它避免了实际的数据库删除操作。
  • 缺点

    • 维护开销:需要定期清理未使用的数据,否则可能会占用过多的存储空间。
    • 查询复杂性 :每个查询都需要包含IsDeleted条件,除非确实需要访问已删除的数据。

多租户

多租户架构是一种将多个租户(用户或组织)共享同一套应用程序或系统的方式,同时保持每个租户的数据隔离性。这种架构模式在许多现代应用程序中被广泛使用,例如云服务提供商、SaaS应用程序等。

以下是一个示例

  1. 定义实体:首先,你需要定义包含特定属性的实体类,例如用于标识租户的TenantId属性。、
cs 复制代码
public class MyEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int TenantId { get; set; }
}
  1. 配置筛选器:接下来,在OnModelCreating方法中使用HasQueryFilter API为实体类型配置查询筛选器。这些筛选器以LINQ查询谓词的形式存在,并自动应用于所有相关的查询操作。
cs 复制代码
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyEntity>()
        .HasQueryFilter(e => e.TenantId == _currentTenantId);
}
  1. 执行查询操作:当你需要查询数据时,只需根据当前租户的ID进行过滤即可。
cs 复制代码
// 假设当前租户的ID为1
var entities = context.MyEntities.ToList();
  1. 添加新记录:当你需要添加一个新记录时,只需设置TenantId属性为当前租户的ID即可。
cs 复制代码
var entity = new MyEntity { Name = "Example" };
entity.TenantId = _currentTenantId;
context.MyEntities.Add(entity);
await context.SaveChangesAsync();

优缺点:

  • 优点

    • 可定制性和灵活性:每个租户可以根据需要定制自己的数据视图和功能。
    • 简化维护:可以在一个集中的位置更新和维护应用程序。
  • 缺点

    • 数据隔离:需要小心设计以防止数据泄露或混肴。
    • 性能挑战:如果所有租户都在同一时间活跃,可能会对性能造成压力。
    • 备份和恢复:可能需要更复杂的备份和恢复策略来满足不同租户的需求。

数据访问权限

下面是一个示例:

假设我们有一个名为User的实体类,其中包含一个名为Role的角色字段,表示用户的角色。我们希望在执行查询时自动过滤掉不属于特定角色的用户。

首先,我们需要在DbContext的OnModelCreating方法中为User实体类型配置全局查询筛选器。

cs 复制代码
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
        .HasQueryFilter(u => u.Role == "Admin");
}

上述代码将自动应用一个筛选条件,只返回角色为"Admin"的用户记录。

接下来,我们可以执行普通的LINQ查询来获取所有管理员用户。

cs 复制代码
var adminUsers = context.Users.ToList();

由于已经配置了全局查询筛选器,上述查询将自动过滤掉非管理员用户,并返回所有管理员用户列表。

全局查询筛选器仅适用于直接查询和通过导航属性引用的情况。如果需要对关联表进行数据访问权限的查询,可以在关联表中也使用类似的全局查询筛选器。还可以根据需要自定义全局查询筛选器的表达式,以满足更复杂的业务需求。


忽略全局查询过滤器( IgnoreQueryFilters()

如果你想在执行针对Student实体类型的查询时忽略全局查询过滤器,可以使用**IgnoreQueryFilters()**方法。

例如,以下代码将忽略全局查询过滤器并返回所有Student记录:

cs 复制代码
var allStudents = context.Students.IgnoreQueryFilters().ToList();

通过调用IgnoreQueryFilters()方法,你可以暂时禁用全局查询过滤器,以便执行不受其影响的查询。

相关推荐
烂蜻蜓6 分钟前
Flask入门教程(三十一):实用函数与类API——全局工具函数速查
后端·python·flask
计算机毕设定制辅导-无忧学长7 分钟前
《基于Spring Boot传承之光非遗陶瓷烧造产品交易平台的设计与实现》
java·vue.js·spring boot·后端·毕业设计
Zane199410 分钟前
内存都要回收,为什么JVM偏要把堆分成新生代和老年代
java·后端
Zane199411 分钟前
257 is 257 为什么是 True?小整数缓存背后还藏着一个更容易被忽略的机制
后端·python
Zhu75811 分钟前
部署安全的pg数据库,搭配pgadmin实现web界面管理
前端·数据库·安全
matlab代码14 分钟前
基于matlab PCA人脸识别系统【源码63期】
开发语言·matlab
Terra.K14 分钟前
后端开发阶段性总结
java·开发语言·后端
学逆向的17 分钟前
PE——合并节
开发语言·网络安全·pe
是个西兰花20 分钟前
C++11:线程库与线程安全问题
开发语言·c++
点心的游戏开发世界22 分钟前
GDScript 入门笔记(十三):字符串操作
开发语言·笔记·游戏引擎·godot