【问题标题】:Catching SQL unique key exceptions in .NET在 .NET 中捕获 SQL 唯一键异常
【发布时间】:2010-10-12 07:22:52
【问题描述】:

我想知道除了解析错误消息之外,是否有人有更优雅的方法来检查 .NET 中 SQL 的唯一键异常?现在我在 SQL 中调用存储过程,然后在 .NET 中使用 try catch 块。在 try catch 块中,我解析了错误消息,这是一个唯一键错误,我将自定义错误的实例抛出给调用类,如果不是,我只是将原始异常抛出调用类。这对我来说似乎非常低效。

【问题讨论】:

    标签: .net asp.net sql


    【解决方案1】:

    如果您捕获到 SqlException,您应该能够枚举包含多个“SqlError”对象的“Errors”集合。

    SqlError 具有“Class”和“Number”等属性 - 唯一键违规是 class= 14 和 number = 2601。检查这些数字以准确找到您的错误。

    这些错误代码与您尝试在 SQL Management Studio 中执行查询时得到的错误代码相同:

    消息 2601,第 14 级,状态 1,第 1 行
    无法在其中插入重复的键行 对象…………
    声明已终止。

    “Msg”转换为 SqlError 上的“Number”属性,“Level”转换为“Class”。

    try
    {
      _cmd.ExecuteNonQuery();
    }
    catch(SqlException sqlExc)
    {
       foreach (SqlError error in sqlExc.Errors)
       {
          string msg = string.Format("{0}: {1}", error.Number, error.Message);
       }
    }
    

    这样,您可以轻松准确地识别“违反唯一约束”错误。

    马克

    【讨论】:

    • 我认为检查“数字”(无类)就足够了。 “类”似乎只说明严重性。
    【解决方案2】:

    你为什么不直接查询唯一 ID 是否存在? 总比异常好。

    【讨论】:

    • +1 用于首先避免异常。您的存储过程应该检查是否存在,如果密钥已经存在,则返回一个众所周知的结果,在这种情况下,您可以在不抛出异常的情况下进行处理,这样效率更高。
    • 除非您使存储过程可序列化,否则您不会随着每秒事务数的增加而遇到并发问题吗?换句话说,在您检查该行不存在并插入它之间,另一个用户已经插入了该行。更不用说首先进行检查的开销了。恕我直言,最好只插入和处理来自 .NET 的错误。
    【解决方案3】:

    解析错误消息是个坏主意。例如,如果您使用 Ms SQL 消息可以本地化(用不同的语言),您将找不到您正在寻找的词。

    如果你使用的是 Ms SQL,你应该检查Number 属性。

    【讨论】:

    • 让我烦恼的是,当涉及到错误代码时,SQL Server 不区分主键违规和唯一约束违规,因为它们都返回 2627。唯一索引违规返回 2601 ,但大多数时候我使用的是 PK 或 UC。关于如何以本地化安全的方式区分 PK 违规和 UC 违规有什么想法吗?
    【解决方案4】:

    显而易见的答案:尝试在插入(或更新)之前从数据库中获取该值,并在插入之前通知用户。

    替代答案:检查 SP 内部的唯一性并将其作为错误消息从 SP 返回,然后您不必解析任何错误。他们都是坏人。

    【讨论】:

      猜你喜欢
      • 2017-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-24
      • 1970-01-01
      相关资源
      最近更新 更多