Entity Framework Core實(shí)現(xiàn)軟刪除與查詢過(guò)濾器
注意:我使用的是 Entity Framework Core 2.0 (2.0.0-preview2-final)。正式版發(fā)布后,功能可能存在變動(dòng)。
繼續(xù)探索Entity Framework Core 2.0,今天我將探討如何輕松使用軟刪除(或邏輯刪除)。我的意思是以透明的方式實(shí)現(xiàn)軟刪除,例如,您是物理上的刪除行。
要實(shí)現(xiàn)軟刪除,您需要添加一列以指示該行數(shù)據(jù)是否被邏輯刪除。如果您想知道該行被刪除,可以使用布爾列,如果您想知道刪除的時(shí)間,可以使用日期列。其次是更改所有查詢,使用此列過(guò)濾結(jié)果集;您還需要將刪除語(yǔ)句替換成為更新語(yǔ)句。
現(xiàn)在我們來(lái)看看如何用 Entity Framework Core 來(lái)實(shí)現(xiàn)這兩件事!
添加IsDeleted列
實(shí)體框架核心提供了非常靈活的映射。在上一篇關(guān)于跟蹤列的博客中,您將找到映射列的3種方法。在介紹中,我已經(jīng)說(shuō)過(guò)軟刪除應(yīng)該是透明的,所以我決定在類型中不暴露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; } }
現(xiàn)在,我們需要向 Entity Framework Core 指明類型有一個(gè)附加列:
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
存儲(chǔ)所有的更改。您可以在EF生成SQL語(yǔ)句和執(zhí)行這些語(yǔ)句之前修改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; } } } }
現(xiàn)在生成以下代碼執(zhí)行的SQL語(yǔ)句:
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
插入和刪除請(qǐng)求已經(jīng)被處理,您現(xiàn)在還必須更改所有查詢語(yǔ)句。
更改查詢語(yǔ)句
Entity Framework Core 2.0 引入了一個(gè)新的概念:查詢過(guò)濾器。查詢過(guò)濾器總是在生成的查詢語(yǔ)句后面追加一個(gè)的where
子句。這意味著,您可以在模型創(chuàng)建時(shí)聲明一個(gè)實(shí)體的過(guò)濾器,然后將此過(guò)濾器隱式添加到使用該表的生成的每個(gè)查詢語(yǔ)句中。
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); } }
讓我們看看查詢過(guò)濾器的作用:
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
查詢過(guò)濾器也可以用于關(guān)聯(lián)查詢:
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]
通過(guò)查詢過(guò)濾器實(shí)現(xiàn)軟刪除非常容易
查詢軟刪除的行
如果您要還原已刪除的行,您必須能夠查詢到這些數(shù)據(jù)。這意味著您需要臨時(shí)刪除查詢過(guò)濾器。EF已經(jīng)添加了一種新方法IgnoreQueryFilters
來(lái)表明您不希望將查詢過(guò)濾器用于當(dāng)前查詢。
var deletedPosts = context.Posts.IgnoreQueryFilters() .Where(post => EF.Property<bool>(post, "IsDeleted") == true);
恢復(fù)已刪除的帖子有點(diǎn)啰嗦,您需要更改跟蹤器中查詢并更新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();
總結(jié)
使用Entity Framework Core 2.0實(shí)現(xiàn)軟刪除模式非常簡(jiǎn)單,并且可以是透明的。實(shí)際上,您可以無(wú)需更改LINQ代碼的情況下,將軟刪除添加到現(xiàn)有模型中。
到此這篇關(guān)于Entity Framework Core實(shí)現(xiàn)軟刪除與查詢過(guò)濾器的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Entity Framework Core使用控制臺(tái)程序生成數(shù)據(jù)庫(kù)表
- Entity Framework Core延遲加載(懶加載)用法
- Entity?Framework?Core實(shí)現(xiàn)Like查詢?cè)斀?/a>
- Entity Framework Core中執(zhí)行SQL語(yǔ)句和存儲(chǔ)過(guò)程的方法介紹
- Entity Framework Core批處理SQL語(yǔ)句
- Entity Framework Core生成列并跟蹤列記錄
- ASP.NET Core在WebApi項(xiàng)目中使用MiniProfiler分析Entity Framework Core
- Entity Framework Core工具使用命令行
- Entity?Framework?Core關(guān)聯(lián)刪除
- 詳解如何在ASP.NET Core中應(yīng)用Entity Framework
- Entity Framework Core對(duì)Web項(xiàng)目生成數(shù)據(jù)庫(kù)表
相關(guān)文章
.NET連接數(shù)據(jù)庫(kù)以及基本的增刪改查操作教程
這篇文章主要給大家介紹了關(guān)于.NET連接數(shù)據(jù)庫(kù)以及基本的增刪改查操作教程的相關(guān)資料,對(duì)于剛?cè)腴T的新手們來(lái)說(shuō)是個(gè)很好的入門教程,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01ASP.NET Core中使用xUnit進(jìn)行單元測(cè)試
這篇文章主要介紹了ASP.NET Core中使用xUnit進(jìn)行單元測(cè)試,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11ASP.NET Core 2.1 使用Docker運(yùn)行的方法步驟
這篇文章主要介紹了ASP.NET Core 2.1 使用Docker運(yùn)行的方法步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07asp.net 分頁(yè)顯示數(shù)據(jù)表的數(shù)據(jù)的代碼
asp.net顯示第一頁(yè)、上一頁(yè)、下一頁(yè)和最后一頁(yè)的分頁(yè)顯示數(shù)據(jù)表的數(shù)據(jù)2010-03-03Asp.net mvc在view中用C#代碼動(dòng)態(tài)創(chuàng)建元素
這篇文章主要給大家介紹了關(guān)于Asp.net mvc如何在view中用C#代碼動(dòng)態(tài)創(chuàng)建元素的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-0312306動(dòng)態(tài)驗(yàn)證碼啟發(fā)之ASP.NET實(shí)現(xiàn)動(dòng)態(tài)GIF驗(yàn)證碼(附源碼)
這篇文章主要介紹了受到12306動(dòng)態(tài)驗(yàn)證碼啟發(fā),實(shí)現(xiàn)ASP.NET動(dòng)態(tài)GIF驗(yàn)證碼,需要的朋友可以參考下2015-08-08ASP.NET?MVC通過(guò)勾選checkbox更改select的內(nèi)容
這篇文章介紹了ASP.NET?MVC通過(guò)勾選checkbox更改select內(nèi)容的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09Repeater全選刪除和分頁(yè)實(shí)現(xiàn)思路及代碼
Repeater控件想必熟悉.net web開(kāi)發(fā)的人員是很了解不過(guò)的了,接下來(lái)將與大家共同學(xué)習(xí)下它的全選刪除和分頁(yè),感興趣的你可不要錯(cuò)過(guò)了哈,希望可以幫助到你2013-03-03