广告
返回顶部
首页 > 资讯 > 后端开发 > ASP.NET >EntityFrameworkCore实现软删除与查询过滤器
  • 784
分享到

EntityFrameworkCore实现软删除与查询过滤器

2024-04-02 19:04:59 784人浏览 泡泡鱼
摘要

注意:我使用的是 Entity Framework Core 2.0 (2.0.0-preview2-final)。正式版发布后,功能可能存在变动。 继续探索Entity Frame

注意:我使用的是 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]

通过查询过滤器实现软删除非常容易

查询软删除的行

如果您要还原已删除的行,您必须能够查询到这些数据。这意味着您需要临时删除查询过滤器。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实现软删除与查询过滤器的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: EntityFrameworkCore实现软删除与查询过滤器

本文链接: https://www.lsjlt.com/news/139908.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • EntityFrameworkCore实现软删除与查询过滤器
    注意:我使用的是 Entity Framework Core 2.0 (2.0.0-preview2-final)。正式版发布后,功能可能存在变动。 继续探索Entity Frame...
    99+
    2022-11-13
  • RocketMQ消息过滤与查询的实现
    消息过滤 RocketMQ分布式消息队列的消息过滤方式有别于其它MQ中间件,是在Consumer端订阅消息时再做消息过滤的。 RocketMQ这么做是还是在于其Producer端写入...
    99+
    2022-11-12
  • SQL汇总统计与GROUPBY过滤查询实现
    目录1、汇总统计2、GROUT BY3、如何对分组统计的结果进行过滤4、如何对分组统计的结果进行排序5、介绍SELECT语句中各个子句的书写顺序6、上方用到的表1、汇总统计 ...
    99+
    2023-01-05
    SQL汇总统计 SQL GROUP BY
  • SQL汇总统计与GROUP BY过滤查询实现
    目录1、汇总统计2、GROUT BY3、如何对分组统计的结果进行过滤4、如何对分组统计的结果进行排序5、介绍SELECT语句中各个子句的书写顺序6、上方用到的表1、汇总统计 介绍几个聚集函数 有多少名学生 SE...
    99+
    2023-01-05
    SQL汇总统计 SQLGROUPBY
  • MongoDB Driver 中通过过滤器实现文档查询
    一、举例:在物流币点击记录里面查询出 同一IP,同一条线路,同一页面,四小时内点击次数     思路:1、根据当前查询的时间将时间回退到四小时前,然后将四小时前的时间转换为时间戳,然后组合其它条件查询 出大于对应时间戳的所有记录数。 ...
    99+
    2017-11-06
    MongoDB Driver 中通过过滤器实现文档查询 数据库入门 数据库基础教程 数据库 mysql
  • 如何实现一个Laravel查询过滤器
    今天小编给大家分享一下如何实现一个Laravel查询过滤器的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。上下文在撰写本文时,...
    99+
    2023-07-05
  • Angular如何实现内置过滤器orderBy排序与模糊查询功能
    小编给大家分享一下Angular如何实现内置过滤器orderBy排序与模糊查询功能,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!...
    99+
    2022-10-19
  • J-Hi查询过滤器的实现原理是什么
    本篇文章给大家分享的是有关J-Hi查询过滤器的实现原理是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。J-Hi设计自己的查询过滤器而没有直接采用Hibernate的Crit...
    99+
    2023-06-17
  • MyBatis-Plus使用条件构造器实现不同条件的查询,更新删除操作
    Wrapper 是所有条件构造器的父类,作用是生成条件语句,即where后面的sql子句 在调用查询,更新,删除操作时,需要根据条件进行判断,可以使用条件构造器进行组合条件,生成where后面条件子句 QueryWrap...
    99+
    2023-08-31
    sql mysql 数据库
  • sql server中怎么通过查询分析器实现数据库备份与恢复
    这篇文章将为大家详细讲解有关sql server中怎么通过查询分析器实现数据库备份与恢复,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。sql server的...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作