EF CORE DELETE

        public void Delete()
        {
            testDbContext.Order.Remove(testDbContext.Order.Find(1006));
            testDbContext.SaveChanges();
        }

這種方式會執行兩次sql語句,第一次是將實體查詢出來,第二次是執行刪除語句

通過上下文查詢出來的實體都會被標記一個狀態Unchanged,再執行Remove方法時會標記狀態爲deleted,調用savechenges方法則會執行刪除的sql語句。

 public void Delete1()
        {
            var order = new Order { OrderId = 1007 };
            testDbContext.Entry(order).State = EntityState.Deleted;
            testDbContext.SaveChanges();
        }

        public void Delete2()
        {
            var order = new Order { OrderId = 1007 };
            testDbContext.Order.Remove(order);
            testDbContext.SaveChanges();
        }

上面兩種方式都會執行一條sql語句,在new 實體類中,主鍵屬性被定義就行了。

 

關係表刪除

僅當使用 EF Core 刪除主體且將依賴實體加載到內存中(即對於跟蹤的依賴項)時才應用 EF Core 模型中配置的刪除行爲。 需要在數據庫中設置相應的級聯行爲以確保未由上下文跟蹤的數據已應用必要的操作。 如果使用 EF Core 創建數據庫,將爲你設置此級聯行爲。

可選關係(就是外鍵值可以設置成null)

對於可選關係(可以爲 null 的外鍵),可以保存 null 外鍵值,從而產生以下影響:

行爲名稱 對內存中的依賴項/子項的影響 對數據庫中的依賴項/子項的影響
Cascade 刪除實體 刪除實體
ClientSetNull(默認) 外鍵屬性設置爲 null
SetNull 外鍵屬性設置爲 null 外鍵屬性設置爲 null
Restrict

必選關係(就是外鍵值不可以設置成null)

對於必選關係(不可爲 null 的外鍵),_不可以_保存 null 外鍵值,從而產生以下影響:

行爲名稱 對內存中的依賴項/子項的影響 對數據庫中的依賴項/子項的影響
Cascade(默認) 刪除實體 刪除實體
ClientSetNull SaveChanges 引發異常
SetNull 引發 SaveChanges 引發 SaveChanges
Restrict

在上表中,“無” 可能會造成約束衝突。 例如,如果已刪除主體/子實體,但不執行任何操作來更改依賴項/子項的外鍵,則由於發生外鍵約束衝突,數據庫將可能會引發 SaveChanges。

高級別:

  • 如果實體在沒有父項時不能存在,且希望 EF 負責自動刪除子項,則使用“Cascade” 。
    • 在沒有父項時不能存在的實體通常使用必選關係,其中“Cascade” 是默認值。
  • 如果實體可能有或可能沒有父項,且希望 EF 負責爲你將外鍵變爲 null,則使用“ClientSetNull”
    • 在沒有父項時可以存在的實體通常使用可選關係,其中“ClientSetNull” 是默認值。
    • 如果希望數據庫即使在未加載子實體時也嘗試將 null 值傳播到子外鍵,則使用“SetNull” 。 但是,請注意,數據庫必須支持此操作,並且如此配置數據庫可能會導致其他限制,實際上這通常會使此選項不適用。 這就是SetNull不是默認值的原因。
  • 如果不希望 EF Core 始終自動刪除實體或自動將外鍵變爲 null,則使用“Restrict” 。 請注意,這要求使用代碼手動同步子實體及其外鍵值,否則將引發約束異常。

不管EF CORE默認是什麼,我們都可以手動修改默認值,如我的例子中,因爲沒有強加外鍵不可爲空,所以默認的級聯刪除,會刪除父類,而將子類的外鍵設置成null

也可以自定義屬性

 protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
         
           modelBuilder.Entity<Order>().HasOne(f => f.User).WithMany(a => a.Orders).OnDelete(DeleteBehavior.Cascade);
           
        }

這樣刪除父類的時候會同時將子類刪除掉

 public void DeleteRelation()
        {
            testDbContext.User.Remove(testDbContext.User.Include(a=>a.Orders).FirstOrDefault(t=>t.UserId==1007));
            testDbContext.SaveChanges();
        }
TestEFCore> Executed DbCommand (39ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
TestEFCore> SELECT TOP(1) [a].[UserId], [a].[DefaultCurrencyCode], [a].[FirstName], [a].[LastName], [a].[SecurityLevel]
TestEFCore> FROM [User] AS [a]
TestEFCore> WHERE [a].[UserId] = 1008
TestEFCore> ORDER BY [a].[UserId]
TestEFCore> 
TestEFCore> Executed DbCommand (4ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
TestEFCore> SELECT [a.Orders].[OrderId], [a.Orders].[Address], [a.Orders].[City], [a.Orders].[Country], [a.Orders].[Customer], [a.Orders].[OrderDate], [a.Orders].[Timestamp], [a.Orders].[UserId]
TestEFCore> FROM [Order] AS [a.Orders]
TestEFCore> INNER JOIN (
TestEFCore>     SELECT TOP(1) [a0].[UserId]
TestEFCore>     FROM [User] AS [a0]
TestEFCore>     WHERE [a0].[UserId] = 1008
TestEFCore>     ORDER BY [a0].[UserId]
TestEFCore> ) AS [t] ON [a.Orders].[UserId] = [t].[UserId]
TestEFCore> ORDER BY [t].[UserId]
TestEFCore> 
TestEFCore> Executed DbCommand (1ms) [Parameters=[@p0='?' (DbType = Int32), @p1='?' (Size = 8) (DbType = Binary)], CommandType='Text', CommandTimeout='30']
TestEFCore> SET NOCOUNT ON;
TestEFCore> DELETE FROM [Order]
TestEFCore> WHERE [OrderId] = @p0 AND [Timestamp] = @p1;
TestEFCore> SELECT @@ROWCOUNT;
TestEFCore> 
TestEFCore> Executed DbCommand (0ms) [Parameters=[@p2='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
TestEFCore> SET NOCOUNT ON;
TestEFCore> DELETE FROM [User]
TestEFCore> WHERE [UserId] = @p2;
TestEFCore> SELECT @@ROWCOUNT;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章