5

我希望能夠檢查從SQL Server 2008中的表中刪除行是否會由於外鍵違例而未嘗試刪除而失敗。檢查是否安全刪除一行

基本上,我不想向用戶顯示一個刪除按鈕,如果他們不能刪除它,因爲密鑰在其他地方使用。

我在應用程序的許多地方都需要這樣,因此不需要手動編寫檢查以查看是否可以安全地刪除該行。有關實現此目標的最佳方法的任何建議?

我正在使用實體框架訪問數據。

回答

2

沒有快速簡單的方法來檢查這一點。你可以使用information_schema來構建一些動態的東西,但它無疑會變得醜陋而不是很快。

絕對的最佳選擇是用於驗證每個位置的自定義代碼的幾行代碼。

另一個選擇是啓動一個事務,嘗試刪除。如果失敗,那麼你知道。如果成功,則回滾事務,並且您知道刪除是可能的。這仍然是醜陋的,並且以一種有點破碎的方式使用交易,但它會起作用。儘管如此,請確保級聯刪除不在桌面上。

1

我在之前的應用程序中做過這種事情。我創建了一個名爲TryDelete()的函數。在該方法中,我試圖刪除所需的行。如果我得到FK異常,我就會抓到它並返回false。在任何一種情況下,true或false,我都將delete封裝在一個事務中,然後將其回滾。

2

查詢時,對子表執行LEFT JOIN。使用CanDelete計算值來決定是否顯示按鈕。如果您每個父行有多於1個子行,COUNT此處將刪除重複項。

SELECT 
    Col1, Col2, Col3, ..., 
    CASE C.Existence WHEN 0 THEN 1 ELSE 0 END AS CanDelete 
FROM 
    ParentTable P 
    LEFT JOIN 
    (
    SELECT COUNT(*) AS Existence, FKColumn 
    FROM Childtable GROUP BY FKColumn 
    ) C ON P.FKColumn = C.FKColumn 
WHERE 
    P.Col = ... 

另一種方式可能是

SIGN(C.Existence) AS HasChildRows 
+0

好主意!但是,他正在使用EntityFramework將數據加載到對象中... – veljkoz 2010-11-23 14:16:35

1

你可以在局部類的實體是否存在被引用的對象,將檢查方法的補充。

例如,假設您有Entity1,其中包含Entity2的集合。基本上,每一個實體的部分類,你會寫一個屬性IsReferenced會:

  • 對於ENTITY1返回true,如果ENTITY1在ENTITY2
  • 任何項目ENTITY2返回TURE如果有到ENTITY1
  • 參考

正如你猜測,你需要確保你始終在參考值的獲取,或者,如果你的工作連接上下文,你可以使用.Load()IsReferenced檢查之前獲取實體。這是一個開銷,它只取決於你是否願意爲它付費。

然後,您可以根據需要顯示/隱藏「刪除」按鈕,以避免每次重複檢查。

0

我想你在這裏有兩個可能的選擇。由於您不能保證所有關係都將映射到您的OM中,因此您必須在數據庫中檢查它。

您可以嘗試回滾之後一個事務中的實際delting,但如果你有contraint配置了級聯刪除,這也將工作...

另一種方式將提取的所有約束上sysobjects表,並驗證每個表都沒有記錄。但是這需要一些動態的SQL,這也會變得相當混亂。

0

如果您處於數據庫級別,我會加入衝突可能存在的所有表格。

任何返回的記錄都不能被刪除,這意味着剩下的設置可以。

0

假設數據庫被多個用戶使用(絕大多數用戶都使用該數據庫) - 在「檢查」刪除是可能的,並且用戶可能決定刪除該行之間將存在一個機會窗口,在此期間其他人可能會執行一些否定測試結果的活動。

這意味着您可能會顯示「刪除」按鈕,但在您嘗試刪除時,將不再可能。此外,您可能不會顯示刪除按鈕,但在用戶決定刪除該行(但無法找到該按鈕)時,應該允許它們。

沒有辦法避免這些種族。我只是讓人們嘗試刪除它們,但是要準備好處理由於外鍵導致的失敗。

相關問題