Entity Framework Core 软删除与查询过滤器
本文翻译自《Entity Framework Core: Soft Delete using Query Filters》,由于水平有限,故无法保证翻译完全正确,欢迎指出错误。谢谢!
注意:我使用的是 Entity Framework Core 2.0 (2.0.0-preview2-final)。正式版发布后,功能可能存在变动。
继续探索Entity Framework Core 2.0,今天我将探讨如何轻松使用软删除(或逻辑删除)。我的意思是以透明的方式实现软删除,例如,您是物理上的删除行。
要实现软删除,您需要添加一列以指示该行数据是否被逻辑删除。如果您想知道该行被删除,可以使用布尔列,如果您想知道删除的时间,可以使用日期列。其次是更改所有查询,使用此列过滤结果集;您还需要将删除语句替换成为更新语句。
现在我们来看看如何用 Entity Framework Core 来实现这两件事!
添加IsDeleted列
实体框架核心提供了非常灵活的映射。在上一篇关于跟踪列(英文原文)的博客中,您将找到映射列的3种方法。在介绍中,我已经说过软删除应该是透明的,所以我决定在类型中不暴露IsDeleted
属性。类型定义如下:
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
现在,我们需要向 Entity Framework Core 指明类型有一个附加列:
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Post>()
.Property<bool>("IsDeleted");
}
}
更改插入、删除查询
Entity Framework Core 使用ChangeTracker
存储所有的更改。您可以在EF生成SQL语句和执行这些语句之前修改ChangeTracker
。
public class BloggingContext : DbContext
{
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
OnBeforeSaving();
return base.SaveChanges(acceptAllChangesOnSuccess);
}
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
OnBeforeSaving();
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
private void OnBeforeSaving()
{
foreach (var entry in ChangeTracker.Entries<Post>())
{
switch (entry.State)
{
case EntityState.Added:
entry.CurrentValues["IsDeleted"] = false;
break;
case EntityState.Deleted:
entry.State = EntityState.Modified;
entry.CurrentValues["IsDeleted"] = true;
break;
}
}
}
}
现在生成以下代码执行的SQL语句:
using (var context = new BloggingContext())
{
var post = new Post { Blog = blog };
context.Posts.Add(post);
context.SaveChanges();
}
exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [Posts] ([BlogId], [Content], [IsDeleted], [Title])
VALUES (@p1, @p2, @p3, @p4);
SELECT [PostId]
FROM [Posts]
WHERE @@ROWCOUNT = 1 AND [PostId] = scope_identity();
-- @p3 is 0 (false)
',N'@p1 int,@p2 nvarchar(4000),@p3 bit,@p4 nvarchar(4000)',@p1=1,@p2=NULL,@p3=0,@p4=NULL
context.Posts.Remove(post);
context.SaveChanges();
exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Posts] SET [BlogId] = @p0, [Content] = @p1, [IsDeleted] = @p2, [Title] = @p3
WHERE [PostId] = @p4;
SELECT @@ROWCOUNT;
',N'@p4 int,@p0 int,@p1 nvarchar(4000),@p2 bit,@p3 nvarchar(4000)',@p4=1,@p0=1,@p1=NULL,@p2=1,@p3=NULL
插入和删除请求已经被处理,您现在还必须更改所有查询语句。
更改查询语句
Entity Framework Core 2.0 引入了一个新的概念:查询过滤器。查询过滤器总是在生成的查询语句后面追加一个的where
子句。这意味着,您可以在模型创建时声明一个实体的过滤器,然后将此过滤器隐式添加到使用该表的生成的每个查询语句中。
public class BloggingContext : DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Post>()
.Property<bool>("IsDeleted");
modelBuilder.Entity<Post>()
.HasQueryFilter(post => EF.Property<bool>(post, "IsDeleted") == false);
}
}
让我们看看查询过滤器的作用:
var posts = context.Posts.ToList();
SELECT [p].[PostId], [p].[BlogId], [p].[Content], [p].[IsDeleted], [p].[Title]
FROM [Posts] AS [p]
WHERE [p].[IsDeleted] = 0 -- Query filter
查询过滤器也可以用于关联查询:
var blogs = context.Blogs.Include(_ => _.Posts);
SELECT [_].[BlogId], [_].[Url]
FROM [Blogs] AS [_]
ORDER BY [_].[BlogId]
SELECT [p].[PostId], [p].[BlogId], [p].[Content], [p].[IsDeleted], [p].[Title]
FROM [Posts] AS [p]
INNER JOIN (
SELECT [_0].[BlogId]
FROM [Blogs] AS [_0]
) AS [t] ON [p].[BlogId] = [t].[BlogId]
WHERE [p].[IsDeleted] = 0 -- Query filter
ORDER BY [t].[BlogId]
通过查询过滤器实现软删除非常容易
Entity Framework Core 软删除与查询过滤器的更多相关文章
- 【EF】Entity Framework Core 软删除与查询过滤器
本文翻译自<Entity Framework Core: Soft Delete using Query Filters>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 注意 ...
- Entity Framework Core 关联删除
关联删除通常是一个数据库术语,用于描述在删除行时允许自动触发删除关联行的特征:即当主表的数据行被删除时,自动将关联表中依赖的数据行进行删除,或者将外键更新为NULL或默认值. 数据库关联删除行为 我们 ...
- Entity Framework Core 2.0 全局查询过滤器
不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: http://gunnarpeipman.com/2017/08/ef ...
- Entity Framework Core系列之DbContext(删除)
上一篇我们介绍了Entity Framework Core系列之DbContext(修改),这一篇我们介绍下删除数据 修改实体的方法取决于context是否正在跟踪需要删除的实体. 下面的示例中con ...
- Entity Framework Core Like 查询揭秘
在Entity Framework Core 2.0中增加一个很酷的功能:EF.Functions.Like(),最终解析为SQL中的Like语句,以便于在 LINQ 查询中直接调用. 不过Entit ...
- 使用Entity Framework Core需要注意的一个全表查询问题
.NET Core 迁移工作如火如荼,今天在使用 Entity Frameowork Core(又名EF Core)时写了下面这样的 LINQ 查询表达式: .Where(u => u.Id = ...
- .Net Core 2.0生态(4):Entity Framework Core 2.0 特性介绍和使用指南
前言 这是.Net Core 2.0生态生态介绍的最后一篇,EF一直是我喜欢的一个ORM框架,随着版本升级EF也发展到EF6.x,Entity Framework Core是一个支持跨平台的全新版本, ...
- ABP官方文档翻译 9.2 Entity Framework Core
Entity Framework Core 介绍 DbContext 配置 在Startup类中 在模块PreInitialize方法中 仓储 默认仓储 自定义仓储 应用程序特定基础仓储类 自定义仓储 ...
- 【EF】Entity Framework Core 2.0 特性介绍和使用指南
阅读目录 前言 获取和使用 新特性 项目升级和核心API变化 下一步计划 遗憾的地方 回到目录 前言 这是.Net Core 2.0生态生态介绍的最后一篇,EF一直是我喜欢的一个ORM框架,随着版本升 ...
随机推荐
- 部署项目到weblogic时提示文件被锁,导致报错
部署项目到weblogic中出现一个“黄叹号!”.报错如下: (1) Deployment is out of date due to changes in the underlying projec ...
- APUE-文件和目录(一)
4.1 函数stat 函数stat返回与此命名文件有关的信息结构.下面的代码实现了一个工具,显示树形目录结构,需要加两个参数,一个为目录名,一个为显示目录的深度. #include <sys/s ...
- 一步一步实现android studio代码上传到github。
本文只注重代码上传能成功就好,不解释什么是git什么事github,git有什么优势. 1,先创建一个android应用, 第二步:创建github账户 和 安装git.网上的文章多如牛毛.唯一要说的 ...
- JVM-1.编译
目录 一.编译器概述 二.编译器组成 三.示例 四.深入理解JVM中的编译器 五.语法糖 六.补充 一.编译器概述 1.编译器实质 编译器的实质是将一种语言规范转化为另一种语言规范:由人容易理 ...
- C语言指针声明探秘
C语言指针声明探秘
- Azure 基础:Blob Storage
Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table. 笔者在前文中介绍了 Table Storage 的基本 ...
- 1.JAVA WEB 笔记中文乱码
JAVA WEB 乱码问题解析 乱码原因 在Java Web开发过程中,经常遇到乱码的问题,造成乱码的原因,概括起来就是对字符编码和解码的方式不匹配. 既然乱码的原因是字符编码与解码的方式不匹配,那么 ...
- 有关苹果无法导出p12证书的问题解决办法。
原因一 所选类型选择错误.解决办法:左侧有两个分类,一个是钥匙串,一个是种类,要选择种类中的我的证书或者证书.然后在右侧证书列表中,右键导出即可. 原因二 使用钥匙串生成的证书有问题,格式为(cert ...
- centos 6.6 ios镜像文件 下载 官网和阿里云两种方式教你下载
1百度一下:centos 打开打开官网.选择这一项 CET CENTOS 2选择 DVD ISO,双击下载 直接选择左键点击下载 这里需要迅雷 方法 二 打开 https://mirrors.aliy ...
- 一起学习c++11——c++11中的新增的容器
c++11新增的容器1:array array最早是在boost中出现:http://www.boost.org/doc/libs/1_61_0/doc/html/array.html 当时的初衷是希 ...