注意:我使用的是 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 软删除与查询过滤器相关推荐

  1. Entity Framework Core 2.0 全局查询过滤器

    本博文翻译自: http://gunnarpeipman.com/2017/08/ef-core-global-query-filters/ Entity Framework Core 2.0 全局查 ...

  2. Entity Framework Core 执行SQL语句和存储过程

    无论ORM有多么强大,总会出现一些特殊的情况,它无法满足我们的要求.在这篇文章中,我们介绍几种执行SQL的方法. 表结构 在具体内容开始之前,我们先简单说明一下要使用的表结构. public clas ...

  3. Entity Framework Core 批处理语句

    在Entity Framework Core (EF Core)有许多新的功能,最令人期待的功能之一就是批处理语句.那么批处理语句是什么呢?批处理语句意味着它不会为每个插入/更新/删除语句发送单独的请 ...

  4. Entity Framework Core 命名约定

    注意:我使用的是 Entity Framework Core 2.0 (2.0.0-preview2-final).正式版发布时,功能可能存在变动.Entity Framework 迁移允许从模型生成 ...

  5. Entity Framework Core 2.1带来更好的SQL语句生成方案

    微软发布了Entity Framework Core2.1,为EF开发者带来了很多期待已久的特性.EF Core 2.1增加了对SQL GROUP BY的支持,支持延迟加载和数据种子等. EF Cor ...

  6. Entity Framework Core 5中实现批量更新、删除

    本文介绍了一个在EntityFramework Core 5中不需要预先加载数据而使用一句SQL语句批量更新.删除数据的开发包,并且分析了其实现原理,并且与其他实现方案做了比较. 一.背景 随着微软全 ...

  7. Entity Framework Core Like 查询揭秘

    在Entity Framework Core 2.0中增加一个很酷的功能:EF.Functions.Like(),最终解析为SQL中的Like语句,以便于在 LINQ 查询中直接调用. 不过Entit ...

  8. Entity Framework Core系列教程-23-原生SQL查询

    在Entity Framework Core中执行原生SQL查询 Entity Framework Core提供了DbSet.FromSql()方法来对基础数据库执行原始SQL查询,并将结果作为实体对 ...

  9. Entity Framework Core 2.0的新特性

    虽然EF Core 2.0存在大量槽点,但是它也给出了不少亮点.在本文中,我们将介绍这次发布版的部分亮点. \\ 数据库表切分(Table Splitting) \\ ORM常被吐槽是总是对所请求数据 ...

最新文章

  1. 第一次作业,针对软件工程这门课程提出五个疑问。
  2. 使用php与mysql构建我们的网站
  3. jQuery的ajax的post请求json格式无法上传空数组
  4. 弗尤博客(十一)之搜索博文
  5. 2019年创业融资去哪个平台好?创成汇
  6. [Luogu 1730]最小密度路径
  7. 有关javabean的说法不正确的是_7、关于JavaBean,下列叙述中不正确的是
  8. ArcGIS中文注记图层发布服务后变乱码(方框乱码)/如何有效修改注记要素类文字样式
  9. Xor异或是什么意思? - 已解决 - 搜搜问问
  10. 人群疏散matlab程序,人群疏散方法及系统与流程
  11. LVDS通信接口详细介绍
  12. codesmith mysql 模板_CodeSmith代码自动生成器 JAVA模版的制作---CodeSmith+MySQL+MyEclipse 10...
  13. tftpd32服务器软件在Windows与linux 下的文件传输
  14. 爱的杂篇--掉掉眼泪
  15. 电脑自动开机是什么原因
  16. 2018春招Android实习生面试感悟
  17. DNS服务安装及配置实验
  18. java微信分享朋友圈_java怎么实现微信分享到朋友圈功能
  19. php获取访客精确ip,PHP获取访客IP、地区位置等技巧分享
  20. 论文阅读:Entangled Watermarks as a Defense against Model Extraction

热门文章

  1. SpringMvc项目中使用GoogleKaptcha 生成验证码
  2. maven 导入数据库
  3. 读jQuery之二十(Deferred对象)
  4. 真人拳皇项目Alpha阶段的回顾——史经浩
  5. [存档]CxServer的项目周期管理
  6. c#书写规范之---代码书写规范
  7. 在 .NET 6 中使用 DATEONLY 和 TIMEONLY
  8. ABP Framework V4.4 RC 新增功能介绍
  9. efcore技巧贴-也许有你不知道的使用技巧
  10. 你真的清楚DateTime in C#吗?