2011-05-25 154 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