<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
注意:我使用的是 Entity Framework Core 2.0 (2.0.0-preview2-final)。正式版釋出後,功能可能存在變動。
繼續探索Entity Framework Core 2.0,今天我將探討如何輕鬆使用軟刪除(或邏輯刪除)。我的意思是以透明的方式實現軟刪除,例如,您是物理上的刪除行。
要實現軟刪除,您需要新增一列以指示該行資料是否被邏輯刪除。如果您想知道該行被刪除,可以使用布林列,如果您想知道刪除的時間,可以使用日期列。其次是更改所有查詢,使用此列過濾結果集;您還需要將刪除語句替換成為更新語句。
現在我們來看看如何用 Entity Framework Core 來實現這兩件事!
實體框架核心提供了非常靈活的對映。在上一篇關於跟蹤列的部落格中,您將找到對映列的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實現軟刪除與查詢過濾器的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45