2012-12-26 43 views
1

我有兩個表,一個表A是父級和其他表B是子級(1:N關係)。交易是刪除兒童記錄的好選擇嗎?

如果我想刪除表B中的子記錄,當我刪除表A中的父項時,如果我不在數據庫中使用級聯刪除,我會按照以下方式執行:

  1. 用戶負載在她的上下文中的父記錄,然後加載的背景下,所有的孩子記錄,全部標記爲刪除。
  2. 其他用戶添加新的孩子。
  3. 用戶A保存更改。獲取參考完整性的錯誤,因爲第二個用戶添加的註冊不在她的上下文中。

在這種情況下,第一個用戶可以嘗試在引發異常時再次加載所有子代,但是第三個用戶可以添加新的子代並具有相同的問題。從理論上講,這可能會一直髮生,並且第一個用戶不會刪除父項。

出於這個原因,我想使用一個交易做的工作。

  1. 首先用戶啓動一個事務。
  2. 第一個用戶標記爲已刪除父級並保存更改。父級在數據庫中被阻塞。
  3. 第一個用戶加載所有的孩子,標記爲已刪除。
  4. 第一位用戶保存更改。

在這種情況下,我懷疑當第一個用戶阻止父註冊時,這個父註冊的ID可以被其他用戶用作子註冊的外鍵?或者數據庫不允許使用該ID,因爲從理論上講,這是一個刪除記錄?

如果數據庫不允許使用的ID,第二個用戶將得到一個異常,當嘗試添加一個新的孩子,僅供參考完整性,因爲家長不存在。所以問題解決了。不需要做任何事情。

但是,如果數據庫允許使用阻斷母體的ID,我需要做兩件事情:

在這種刪除父方法:

  1. 負載的父母,將其標記作爲刪除並保存更改。這會阻止寄存器。
  2. 加載孩子,將其標記爲已刪除並保存更改。
  3. 接受交易。

在該加入兒童

  1. 負載親本方法。如果被阻塞,該方法將一直等到寄存器空閒。
  2. 添加新的孩子。
  3. 接受更改。

真的不需要在上下文中加載父項來刪除子項,這將是對數據庫的額外查詢。

如果父母不存在,那麼得到一個異常不需要做任何事情,現在嘗試添加一個新註冊的用戶是因爲父母被刪除了。

如果父母存在,則可以添加孩子。

所以我有兩個問題。

  1. 使用事務刪除父記錄以確保所有子項都被刪除是一個好主意?

  2. 如果一個事務是一個很好的選擇,當父母被阻止時,數據庫不允許使用父母ID來添加新記錄,或者我需要做的解決方案來加載父母的方法刪除孩子?

+0

您不能將父母標記爲已刪除並保存更改。 EF將嘗試刪除該記錄並違反FK約束。或者,您是否通過在數據庫字段中設置標記來將其標記爲已刪除? –

+0

如果我沒有錯,如果我在交易中,當標記爲已刪除的父項並進行第一次保存更改時,沒有任何問題,因爲我仍然不支付交易。但是這在理論上,我還沒有做過測試。 –

回答

1

交易不推遲刪除操作。數據庫中沒有任何東西像「被標記爲已刪除」。當您將實體標記爲已刪除並執行SaveChanges時,該記錄將在數據庫中刪除。它總是發生在交易中。一旦記錄即將被刪除FK限制被檢查並且如果存在任何從屬記錄則拋出錯誤(除非約束規則ON DELETE未定義其他選項)。使用FK限制時,必須始終在父級之前刪除子級。

如果您的描述是準確的,您可以簡單地使用你害怕的第一種方法,並關閉查詢並將SaveChanges合併成單個TransactionScope。它將以可序列化的隔離級別運行事務,這應確保在當前事務完成之前,沒有其他事務能夠將記錄插入鎖定鍵範圍(由查詢鎖定)。

儘管可序列化事務的解決方案可能會起作用,但它可能會帶來其他問題 - 與應用程序中的其他事務發生死鎖。由於重複失敗的交易往往是最好的選擇。如果您的系統具有如此大的併發負載,那麼刪除事務可能會「一直」失敗,這可能是徹底重新設計應用程序的時候了。

+0

事務範圍中的可序列化隔離級別而不是readCommited? –

+0

,如果我決定使用重複失敗的交易解決方案,多少次嘗試是一個好數字? 10,20,50 ...?並且數據庫的性能不受影響很大? –

+0

'TransactionScope'中的可序列化事務級別。可序列化事務對數據庫有負面影響。影響取決於交易阻止的併發請求數。 –