Entity Framework Core 软删除与查询过滤器
注意:我使用的是 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] = @p3WHERE [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 filterORDER BY [t].[BlogId]
通过查询过滤器实现软删除非常容易 :)
查询软删除的行
如果您要还原已删除的行,您必须能够查询到这些数据。这意味着您需要临时删除查询过滤器。EF已经添加了一种新方法IgnoreQueryFilters
来表明您不希望将查询过滤器用于当前查询。
var deletedPosts = context.Posts.IgnoreQueryFilters() .Where(post => EF.Property<bool>(post, "IsDeleted") == true);
恢复已删除的帖子有点啰嗦,您需要更改跟踪器中查询并更新IsDeleted
属性。
var deletedPosts = context.Posts.IgnoreQueryFilters().Where(post => EF.Property<bool>(post, "IsDeleted") == true);foreach (var deletedPost in deletedPosts)
{ var postEntry = context.ChangeTracker.Entries<Post>().First(entry => entry.Entity == deletedPost);postEntry.Property("IsDeleted").CurrentValue = false;
}
context.SaveChanges();
总结
使用Entity Framework Core 2.0实现软删除模式非常简单,并且可以是透明的。实际上,您可以无需更改LINQ代码的情况下,将软删除添加到现有模型中。
相关文章:
Entity Framework Core 生成跟踪列
在Apworks数据服务中使用基于Entity Framework Core的仓储(Repository)实现
Entity Framework Core的贴心:优雅处理带默认值的数据库字段
Entity Framework Core 实现MySQL 的TimeStamp/RowVersion 并发控制
原文地址:http://www.cnblogs.com/tdfblog/p/entity-framework-core-soft-delete-using-query-filters.html
.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注
Entity Framework Core 软删除与查询过滤器相关推荐
- Entity Framework Core 2.0 全局查询过滤器
本博文翻译自: http://gunnarpeipman.com/2017/08/ef-core-global-query-filters/ Entity Framework Core 2.0 全局查 ...
- Entity Framework Core 执行SQL语句和存储过程
无论ORM有多么强大,总会出现一些特殊的情况,它无法满足我们的要求.在这篇文章中,我们介绍几种执行SQL的方法. 表结构 在具体内容开始之前,我们先简单说明一下要使用的表结构. public clas ...
- Entity Framework Core 批处理语句
在Entity Framework Core (EF Core)有许多新的功能,最令人期待的功能之一就是批处理语句.那么批处理语句是什么呢?批处理语句意味着它不会为每个插入/更新/删除语句发送单独的请 ...
- Entity Framework Core 命名约定
注意:我使用的是 Entity Framework Core 2.0 (2.0.0-preview2-final).正式版发布时,功能可能存在变动.Entity Framework 迁移允许从模型生成 ...
- Entity Framework Core 2.1带来更好的SQL语句生成方案
微软发布了Entity Framework Core2.1,为EF开发者带来了很多期待已久的特性.EF Core 2.1增加了对SQL GROUP BY的支持,支持延迟加载和数据种子等. EF Cor ...
- Entity Framework Core 5中实现批量更新、删除
本文介绍了一个在EntityFramework Core 5中不需要预先加载数据而使用一句SQL语句批量更新.删除数据的开发包,并且分析了其实现原理,并且与其他实现方案做了比较. 一.背景 随着微软全 ...
- Entity Framework Core Like 查询揭秘
在Entity Framework Core 2.0中增加一个很酷的功能:EF.Functions.Like(),最终解析为SQL中的Like语句,以便于在 LINQ 查询中直接调用. 不过Entit ...
- Entity Framework Core系列教程-23-原生SQL查询
在Entity Framework Core中执行原生SQL查询 Entity Framework Core提供了DbSet.FromSql()方法来对基础数据库执行原始SQL查询,并将结果作为实体对 ...
- Entity Framework Core 2.0的新特性
虽然EF Core 2.0存在大量槽点,但是它也给出了不少亮点.在本文中,我们将介绍这次发布版的部分亮点. \\ 数据库表切分(Table Splitting) \\ ORM常被吐槽是总是对所请求数据 ...
最新文章
- 第一次作业,针对软件工程这门课程提出五个疑问。
- 使用php与mysql构建我们的网站
- jQuery的ajax的post请求json格式无法上传空数组
- 弗尤博客(十一)之搜索博文
- 2019年创业融资去哪个平台好?创成汇
- [Luogu 1730]最小密度路径
- 有关javabean的说法不正确的是_7、关于JavaBean,下列叙述中不正确的是
- ArcGIS中文注记图层发布服务后变乱码(方框乱码)/如何有效修改注记要素类文字样式
- Xor异或是什么意思? - 已解决 - 搜搜问问
- 人群疏散matlab程序,人群疏散方法及系统与流程
- LVDS通信接口详细介绍
- codesmith mysql 模板_CodeSmith代码自动生成器 JAVA模版的制作---CodeSmith+MySQL+MyEclipse 10...
- tftpd32服务器软件在Windows与linux 下的文件传输
- 爱的杂篇--掉掉眼泪
- 电脑自动开机是什么原因
- 2018春招Android实习生面试感悟
- DNS服务安装及配置实验
- java微信分享朋友圈_java怎么实现微信分享到朋友圈功能
- php获取访客精确ip,PHP获取访客IP、地区位置等技巧分享
- 论文阅读:Entangled Watermarks as a Defense against Model Extraction