2012-06-29 40 views
5

由於EF不支持唯一的密鑰約束,因此我們似乎需要在Save方法期間捕獲異常並向用戶顯示錯誤消息。EF CodeFirst在保存更改時處理數據庫異常

這種方法的問題是:

  • 我們怎麼知道哪個記錄拋出異常
  • 我們怎麼知道什麼樣的問題引發了異常(例如我可能對相同的兩個唯一約束記錄,所以我需要告訴哪一個是打破了用戶)

DBMS是SqlServer的2008年

如何解決這些問題呢?

回答

2

如果允許用戶可以輸入值必須在數據庫中唯一保存更改之前,您應該驗證此輸入:

if (context.Customers.Any(c => c.SomeUniqueProperty == userInput)) 
    // return to user with a message to change the input value 
else 
    context.SaveChanges(); 

這不僅具有唯一約束值的情況下在數據庫中,但也用於輸入必須引用現有目標記錄或主鍵值(如果主鍵未在數據庫中自動生成)的外鍵值。在後一種情況下,EF不會幫助您,因爲上下文不知道整個數據庫表的內容,而只知道當前連接到上下文的實體。確實,EF將禁止使用相同的主鍵連接兩個對象,但允許具有相同唯一鍵約束的兩個對象。但是,當您保存對數據庫的更改時,這並不能完全防範主鍵約束衝突。

在偶然的情況下,該Any檢查和SaveChanges之間的另一個用戶輸入一個記錄具有相同價值,我認爲發生的歷史的例外是不可能的處理,只是告訴用戶「發生預期的錯誤,請嘗試再次...」。如果用戶再次嘗試Any檢查再次發生,他會得到更有用的消息來更改上面的代碼中的輸入值。

針對這種唯一鍵約束或主鍵約束違規返回的異常是一般的DbUpdateException,其中一個內部異常將是SqlException,其中包含SQL Server錯誤代碼的屬性之一。任何其他細節只能在異常消息「違反UNIQUE KEY約束IX_SomeUniqueProperty_Index ...」或類似內容中找到。如果您希望用戶能夠理解並根據這些信息做出相應的反應,您可以顯示它。否則,您可以將此消息記錄給管理員或開發人員以檢查可能的錯誤或其他問題。

+0

因此,由於我正在進行批量更新,因此需要在客戶中查找更新/添加的記錄,並遍歷每條記錄以檢查是否存在具有相同值的現有記錄。我不太清楚當有10多條記錄發生變化時它將如何影響性能。或者在這種情況下,最好只是發現異常?消息必須是本地化的,所以看起來我需要創建一個程序來執行消息搜索IX_SomeUniqueProperty,因爲消息也可以是法語,如果操作系統是法語的(如果我沒有弄錯),我不能依賴關於「違反....」 – Goran

+0

@Goran:我明白了,但我仍然會做一個查詢來檢查是否存在。如果您還需要* update *,那麼不僅需要插入,還是不需要查詢數據庫中的實體?您無法在更新和插入之間做出決定,而無需知道該實體是否已經在數據庫中。 – Slauma

+0

更新和插入之間的決定由EF本身決定。任何我已添加到Customers集合的實體都被視爲新記錄,已更新PK的記錄將被更新。我需要覆蓋的是網絡上的用戶添加記錄的情況(客戶端的數據在大多數情況下不會與數據庫數據保持同步,因爲這需要不斷重新同步),因此可能需要15分鐘數據加載,並保存更改呼叫。基於這個原因,我不僅可以依賴客戶端緩存的數據來檢查是否有唯一的約束(或其他約束)。 – Goran

相關問題