Entity Framework Core中的全局查询过滤器实现与应用
阅读:60
点赞:0
全局查询过滤器(Global Query Filter)是Entity Framework Core中一个非常实用的功能。它允许我们在模型层级定义过滤条件,这些条件会自动应用于所有针对指定类型的查询。简单来说,Entity Framework会在执行LINQ查询之前,自动将过滤条件添加到WHERE子句中。通常,全局查询过滤器在上下文的OnModelCreating
方法中应用。这些过滤器也会自动应用于涉及到的实体类型,包括作为导航属性的间接引用类型。
一. 全局查询过滤器的常见用途
-
软删除:在实体类型中定义一个 IsDeleted
属性,当数据被标记为删除时,应用程序不需要显示这些数据。 -
多租户:在实体类型中定义一个 TenantId
属性,以支持多租户的数据隔离。
二. 示例
2.1 创建Employee表
首先,我们创建一个Employee
表,该表包含一个IsDeleted
列,用于标记记录是否被删除。
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Employee](
[Id] [int] NOT NULL, -- 员工ID,主键
NULL, -- 员工姓名
[IsDeleted] [bit] NULL, -- 是否删除标志
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED
(
[Id] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
-- 插入数据
INSERT [dbo].[Employee] ([Id], [Name], [IsDeleted]) VALUES (1, N'Jignesh', 0)
INSERT [dbo].[Employee] ([Id], [Name], [IsDeleted]) VALUES (2, N'Rakesh', 0)
INSERT [dbo].[Employee] ([Id], [Name], [IsDeleted]) VALUES (3, N'Tejas', 0)
INSERT [dbo].[Employee] ([Id], [Name], [IsDeleted]) VALUES (4, N'Rajesh', 1)
2.2 定义实体和上下文类
Employee.cs
using System.ComponentModel.DataAnnotations; // 引入数据注解
using System.ComponentModel.DataAnnotations.Schema; // 引入数据注解的表和列映射
namespace GlobalFilterExample.Model
{
[Table("Employee")] // 映射到数据库中的Employee表
public class Employee
{
[Key] // 指定Id为主键
public int Id { get; set; } // 员工ID
public string Name { get; set; } // 员工姓名
public bool IsDeleted { get; set; } // 是否删除标志
}
}
EntityModelContext.cs
using Microsoft.EntityFrameworkCore; // 引入Entity Framework Core
using System;
namespace GlobalFilterExample.Model
{
public class EntityModelContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// 配置数据库连接字符串
optionsBuilder.UseSqlServer(@"Server=(local);Database=Test;user Id=sa; password=Passwd@12;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 应用全局查询过滤器
modelBuilder.Entity<Employee>()
.HasQueryFilter(p => !p.IsDeleted); // 过滤掉已删除的记录
base.OnModelCreating(modelBuilder); // 调用基类方法
}
public DbSet<Employee> Employees { get; set; } // DbSet属性,表示Employee表
}
}
2.3 示例代码
using (EntityModelContext context = new EntityModelContext())
{
Console.WriteLine("---------------With Global Query Filters---------------");
// 获取所有未删除的员工
var data = context.Employees.ToList();
foreach (var d in data)
{
Console.WriteLine("{0}\t{1}", d.Id, d.Name); // 输出员工ID和姓名
}
Console.ReadLine();
}
2.4 输出结果
---------------With Global Query Filters---------------
1 Jignesh
2 Rakesh
3 Tejas
三. 禁用全局过滤器
全局查询过滤器会应用于所有LINQ查询。在某些情况下,我们可能不需要这些过滤器。可以使用IgnoreQueryFilters()
方法禁用全局过滤器。
3.1 示例代码
using (EntityModelContext context = new EntityModelContext())
{
// 忽略全局查询过滤器,获取所有员工,包括已删除的记录
var data1 = context.Employees
.IgnoreQueryFilters().ToList();
foreach (var d in data1)
{
Console.WriteLine("{0}\t{1}", d.Id, d.Name); // 输出员工ID和姓名
}
}
3.2 输出结果
1 Jignesh
2 Rakesh
3 Tejas
4 Rajesh
四. 限制
全局查询过滤器有以下限制:
-
不能包含导航属性:过滤器不能引用导航属性。 -
只能在继承层次结构的根实体类型上定义:它只能在继承层次结构的根实体类型上定义。 -
IgnoreQueryFilters
方法会忽略所有过滤器:不能单独移除特定的过滤器。
五. 总结
全局查询过滤器(或模型级查询过滤器)是Entity Framework Core中一个非常有用的功能。它帮助开发者在模型层级上应用过滤条件,防止在开发过程中遗漏某些数据过滤逻辑。这种机制可以确保应用程序始终只处理有效的数据,从而提高了数据的安全性和一致性。