2011-05-25 195 views
11

如何使用c#捕捉特定的異常?
在我的數據庫中有一些列上有唯一索引。
當用戶插入重複記錄這個例外是拋出:捕捉特定的異常

不能在 對象DBO插入重複鍵行。 BillIdentity'與獨特 索引'IX _BillIdentity'。 聲明已被終止。

我該如何發現這個異常?
目前我使用此代碼檢查:

catch (Exception ex) { 
    if (ex.Message.Contains("Cannot insert duplicate key row in object 'dbo._BillIdentity' with unique index 'IX__BillIdentity")) { 
     string ScriptKey = "$(function() {ShowMessage('Error');});"; 
     ScriptManager.RegisterStartupScript(Page, GetType(), "script", ScriptKey, true); 
    } 
} 

我認爲其臭代碼。
有沒有更好的辦法?

+1

爲什麼不在運行insert語句之前檢查鍵是否存在? – 2011-05-25 06:47:19

+0

@Johann Blais,這項工作有什麼好處? – Shahin 2011-05-25 06:49:26

+2

避免您要求的蹩腳的基於異常的解決方法;) – 2011-05-25 07:11:24

回答

9

您沒有顯示類型引發的異常,但您可以捕獲該特定的異常類型。例如:

catch (DuplicateKeyException e) { 
    ... 
} 

這有可能是不會有對只是此錯誤特定的異常類型 - 但是如果你必須抓住的東西相當普遍喜歡SqlException那麼你可以尋找更多的細節在類中本身。例如,在SqlException中,有一個Errors屬性,您可以在數據庫端查看有關每個(可能多個)錯誤的更多詳細信息。每個SqlError然後有一個Number屬性,它會給出錯誤的類型。如果您絕對需要,您可以隨時回覆信息,但您需要了解不同文化的信息變化的可能性等。

請注意,如果你不是真的處理例外,你或許應該重新拋出:

catch (SqlException e) { 
    if (CheckWeCanHandle(e)) { 
     // Mess with the ScriptManager or whatever 
    } else { 
     throw; 
    } 
} 
+0

謝謝,我正在處理這個錯誤在表示層,我不能Rethrow異常。我錯在哪裏? – Shahin 2011-05-25 06:42:06

+1

@Shaah,如果你不能重新拋出,那麼爲什麼要問一個特定的exc?你似乎想要以不同的方式處理它。 – 2011-05-25 06:59:25

+1

@shaahin:你可能*應該*重新拋出任何你實際上不能處理的錯誤,然後有一個整合的錯誤處理表示層的一部分來給出一個合適的錯誤頁面。 – 2011-05-25 07:32:50

24

只有在這種情況下才能處理SqlException

[編輯]

要檢查重複鍵異常的MS SQL服務器:

try 
{ 
    // try to insert 
} 
catch (SqlException exception) 
{ 
    if (exception.Number == 2601) // Cannot insert duplicate key row in object error 
    { 
     // handle duplicate key error 
     return;     
    } 
    else 
     throw; // throw exception if this exception is unexpected 
} 

編輯: 凡2601從何而來?

select * 
from sys.messages 
where text like 'Cannot insert duplicate key%' 

返回:

message_id language_id severity is_event_logged text 
----------- ----------- -------- --------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
2601  1033  14  0    Cannot insert duplicate key row in object '%.*ls' with unique index '%.*ls'. The duplicate key value is %ls. 

使用exception.Number和引用sys.messages查看您可以處理任何特定的MS SQL例外。

+0

你好,亞歷克斯,很好的答案。我正在尋找什麼除了它是一個不同的例外。有關這些例外數字的參考嗎? – 2012-05-04 11:02:21

+1

@LuukKrijnen - 你可以查詢sys.messages這些錯誤代碼。 – 2012-05-06 23:35:13

+0

@AlexAza我可以檢測出發生這種列違規的方式嗎?...我可能在一張桌子上有更多獨特的按鍵,並且想單獨分別對其進行檢測 – Learner 2015-11-25 13:44:05

0

你只能聽對於初學者的SQLEXCEPTION

catch (SqlException ex) { 
    if (ex.Message.Contains("Cannot insert duplicate key row in object 'dbo._BillIdentity' with unique index 'IX__BillIdentity")) { 
     string ScriptKey = "$(function() {ShowMessage('Error');});"; 
     ScriptManager.RegisterStartupScript(Page, GetType(), "script", ScriptKey, true); 
    } 
} 
1

我剛拿起一個項目,有人沿着這條路線:

Catch ex As SqlException 
    Select Case ex.Number 
      Case 2601 
       ... 

請注意以下事項(來自SQL Server中的sys.messages):

2601 - 無法在具有唯一索引'%。* ls'的對象'%。* ls'中插入重複鍵行。

但是,這是怎麼回事?

2627 - 違反%ls約束'%。* ls'。不能在對象中插入重複鍵%。* ls'的。」

我只是花了一些時間跟蹤正是這個問題。

如果我們改變DB提供程序?大概2601絕對不是萬能的...如果你在表現層處理這個問題,我認爲還有更大的問題要問。

如果這個必須是是選擇的機制,那麼把它埋深入深層在DAL中讓一個自定義的Exception滲透起來,這樣,對數據存儲的改變(或者理想的情況下,這個機制)的影響範圍更加有限,你可以處理case consis在表示層中沒有任何問題。

我目前傾向於在打開的連接上爲一個ID做一個輕量級的SELECT並完全避免這個異常。

+0

通過回答很好地思考。我喜歡。 – 2016-02-15 13:26:09