如何使用c#捕获特定异常?
在我的数据库中,某些列上有唯一索引
当用户插入重复记录时,抛出此异常:
无法插入重复的键行 对象'dbo。 BillIdentity'具有独特性 index'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);
}
}
我认为它的难闻的气味代码 还有更好的办法吗?
答案 0 :(得分:28)
仅在这种情况下处理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异常。
答案 1 :(得分:12)
您没有显示抛出的异常的类型,但您可以捕获该特定异常类型。例如:
catch (DuplicateKeyException e) {
...
}
只有这个错误可能没有特定的异常类型 - 但是如果你必须抓住像SqlException
那样相当普遍的东西,你可以在其中查找更多细节班级本身。例如,在SqlException
中有一个Errors
属性,您可以在其中查看有关数据库端每个(可能是多个)错误的更多详细信息。然后每个SqlError
都有一个Number
属性,它将给出错误类型。如果你绝对必须,你总是可以回到这个消息,但是你需要知道消息在不同文化等方面的变化。
请注意,如果你真的没有处理异常,你应该重新抛出它:
catch (SqlException e) {
if (CheckWeCanHandle(e)) {
// Mess with the ScriptManager or whatever
} else {
throw;
}
}
答案 2 :(得分:1)
我刚刚选择了一个有人走这条路的项目:
Catch ex As SqlException
Select Case ex.Number
Case 2601
...
请注意以下内容(来自SQL Server中的sys.messages):
2601 - 无法在对象'%。* ls'中插入具有唯一索引'%。* ls'的重复键行。
但是这个怎么样??
2627 - 违反%ls约束'%。* ls'。无法在对象'%。* ls'中插入重复键。“
我只花了一些时间来追踪这个问题。
如果我们更改数据库提供商怎么办?据推测2601并不是绝对普遍......这很臭,IMO。如果您在演示层中处理此问题,我认为还有更大的问题要问。
如果必须是选择的机制,请将其深入,深入DAL并让自定义异常渗透。这样,对数据存储(或理想情况下,这种机制)的更改具有更有限的效果区域,您可以在表示层中始终如一地处理案例。
我目前倾向于在开放式连接上为ID做一个轻量级的SELECT并完全避免异常。
答案 3 :(得分: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);
}
}
答案 4 :(得分:0)
如here所述,您可以使用异常过滤器。示例:
try
{ /* your code here */ }
catch (SqlException sqlex) when (sqlex.Number == 2627)
{ /* handle the exception */ }
答案 5 :(得分:0)
仅用于过滤器的工作代码重复的主键冲突异常
using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
try {
abc...
} catch (DbUpdateException ex) {
if (ex.InnerException.InnerException is SqlException sqlEx && sqlEx.Number == 2601) {
return ex.ToString();
} else {
throw;
}
}
请注意细节:-ex.InnerException.InnerException
而非ex.InnerException