捕获特定异常

发布于 2024-11-09 17:21:29 字数 608 浏览 1 评论 0原文

如何使用 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);
    }
}

我认为它的代码很难闻。
还有更好的办法吗?

How can I catch specific exception using c# ?
In my database there is unique index on some columns.
when user inserts duplicate record this exception has been throw :

Cannot insert duplicate key row in
object 'dbo.BillIdentity' with unique
index 'IX
_BillIdentity'. The
statement has been terminated.

How can I catch this exception?
Currently I am checking using this code :

 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);
    }
}

I think its bad smell code.
Is there any better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

巡山小妖精 2024-11-16 17:21:29

仅在这种情况下处理SqlException

[编辑]

要检查 MS SQL Server 中的重复键异常:

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 异常。

Handle SqlException only in this case.

[Edit]

To check duplicate key exception in MS SQL server:

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
}

Edit:
Where 2601 come from?

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

Returns:

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.

Using exception.Number and referencing sys.messages view you can handle any specific MS SQL exception.

下雨或天晴 2024-11-16 17:21:29

您尚未显示引发的异常的类型,但您可以捕获该特定异常类型。例如:

catch (DuplicateKeyException e) {
    ...
}

只是此错误可能不会有特定的异常类型 - 但如果您必须捕获像 SqlException 这样相当普遍的东西,那么您可以寻找类本身的更多细节。例如,在 SqlException 中,有一个 Errors 属性,您可以在其中查看有关数据库端每个(可能是多个)错误的更详细信息。每个 SqlError然后有一个 Number 属性将给出错误的类型。如果确实有必要,您可以随时返回该消息,但您需要意识到该消息可能会因不同文化等而发生变化。

请注意,如果您没有真正处理异常,你可能应该重新抛出它:

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

You haven't shown the type of exception which is thrown, but you can catch that specific exception type. For example:

catch (DuplicateKeyException e) {
    ...
}

It's possible that there won't be a specific exception type for just this error - but if you have to catch something fairly general like SqlException you can then look for more details within the class itself. For example in SqlException there's an Errors property where you can look at more detailed information about each of the (possibly multiple) errors at the database side. Each SqlError then has a Number property which will give the type of error. You can always fall back to the message if you absolutely have to, but you then need to be aware of the possibility of the message changing for different cultures etc.

Note that if you're not really handling the exception, you should probably rethrow it:

catch (SqlException e) {
    if (CheckWeCanHandle(e)) {
        // Mess with the ScriptManager or whatever
    } else {
        throw;
    }
}
安稳善良 2024-11-16 17:21:29

我刚刚接手了一个项目,其中有人沿着这条路线走:

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 并完全避免异常。

I've just picked up a project where someone went down this route:

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

Note the following (from sys.messages in SQL Server):

2601 - Cannot insert duplicate key row in object '%.*ls' with unique index '%.*ls'.

But what about this..?

2627 - Violation of %ls constraint '%.*ls'. Cannot insert duplicate key in object '%.*ls'."

I just spent some time tracking down exactly this problem.

And what if we change DB provider? Presumably 2601 is not absolutely universal... This stinks, IMO. And if you are (were) dealing with this in your presentation layer, I think there are bigger questions to ask.

If this must be the mechanism of choice, bury it deep, deep down in the DAL and let a custom Exception percolate up. That way, changes to the data store (or, ideally, this mechanism) have a much more limited area of effect and you can handle the case consistently without any questions in the presentation layer.

I'm currently leaning towards doing a light-weight SELECT for an ID on an open connection and avoiding the exception altogether.

心如狂蝶 2024-11-16 17:21:29

此处所述,您可以使用异常过滤器。例子:

try
{ /* your code here */ }
catch (SqlException sqlex) when (sqlex.Number == 2627)
{ /* handle the exception */ }

As documented here, you can use exception filters. Example:

try
{ /* your code here */ }
catch (SqlException sqlex) when (sqlex.Number == 2627)
{ /* handle the exception */ }
回梦 2024-11-16 17:21:29

仅过滤重复主键违规异常的工作代码

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

Working code for filter only duplicate primary key violation exception

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;
    }
}

Note fine detail :- ex.InnerException.InnerException not ex.InnerException

花开柳相依 2024-11-16 17:21:29

对于初学者来说,您只能捕获 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);
    }
}

You could only catch the SqlException for starters

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文