C#中如何使用EF Core的全局查询过滤器?如何配置?

高手,哪位知道,C#中如何使用EF Core的全局查询过滤器?如何配置?
最新回答
相思故

2026-10-25 10:52:36

在 C# 中使用 EF Core 的全局查询过滤器,可通过 HasQueryFilter 方法在 OnModelCreating 中配置 LINQ 条件,自动应用于实体的所有查询,常用于软删除和多租户场景。

核心配置步骤
  1. 在 DbContext 中重写 OnModelCreating 方法使用 ModelBuilder 的 Entity<T>.HasQueryFilter 方法为实体设置过滤条件。

  2. 示例:实现软删除以下代码为 Blog 和 Post 实体配置了 IsDeleted 过滤条件,所有查询自动排除已删除数据:

    public class BloggingContext : DbContext{ public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .HasQueryFilter(b => !b.IsDeleted); modelBuilder.Entity<Post>() .HasQueryFilter(p => !p.IsDeleted); }}public class Blog{ public int Id { get; set; } public string Name { get; set; } public bool IsDeleted { get; set; }}public class Post{ public int Id { get; set; } public string Title { get; set; } public bool IsDeleted { get; set; } public int BlogId { get; set; } public Blog Blog { get; set; }}

    效果:所有对 Blog 和 Post 的查询(如 context.Blogs.ToList())会自动添加 !IsDeleted 条件,无需手动编写。

忽略全局过滤器的方法

若需查询已软删除的数据,可使用 IgnoreQueryFilters() 方法绕过过滤器:

var deletedBlogs = context.Blogs .IgnoreQueryFilters() .Where(b => b.IsDeleted) .ToList();高级用法:多租户支持

通过依赖注入传递租户 ID,实现每个租户只能访问自己的数据:

public class BloggingContext : DbContext{ private readonly string _tenantId; public BloggingContext(string tenantId) { _tenantId = tenantId; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .HasQueryFilter(b => b.TenantId == _tenantId); }}
  • 安全性:过滤器确保查询仅返回当前租户的数据,避免数据泄露。
注意事项
  1. 性能影响

    复杂过滤表达式可能导致查询性能下降,建议为过滤字段(如 IsDeleted、TenantId)添加数据库索引。

  2. 关联数据过滤

    使用 Include 加载导航属性时,过滤器会应用于关联实体。若关联实体被过滤掉,可能导致数据缺失。

  3. 静态上下文与单例模式

    避免在静态上下文或单例模式下使用依赖注入的过滤器参数(如租户 ID),否则可能导致状态污染。

  4. 数据库迁移

    过滤器仅在应用层生效,数据库层面不会强制约束,迁移时需手动处理数据一致性。

总结
  • 配置简单:通过 HasQueryFilter 一行代码即可实现自动过滤。
  • 适用场景:软删除、多租户、权限控制等需要统一查询条件的场景。
  • 灵活控制:可通过 IgnoreQueryFilters() 临时绕过过滤器,满足特殊查询需求。

合理使用全局查询过滤器可显著减少重复代码,提升开发效率,但需注意性能优化和边界条件处理。