SqlException的catch和处理

问:是否有更好的方法来处理SqlException?

以下示例依赖于解释消息中的文本。

Eg1:如果一个表不存在,我有一个现有的try catch来处理。
忽略我可以检查表是否存在的事实。

try { //code } catch(SqlException sqlEx) { if (sqlEx.Message.StartsWith("Invalid object name")) { //code } else throw; } 

Eg2:没有try catch显示重复键exception

 if (sqlEx.Message.StartsWith("Cannot insert duplicate key row in object")) 

解决scheme:我的SqlExceptionHelper的开始

 //-- to see list of error messages: select * from sys.messages where language_id = 1033 order by message_id public static class SqlExceptionHelper { //-- rule: Add error messages in numeric order and prefix the number above the method //-- 208: Invalid object name '%.*ls'. public static bool IsInvalidObjectName(SqlException sex) { return (sex.Number == 208); } //-- 2601: Cannot insert duplicate key row in object '%.*ls' with unique index '%.*ls'. The duplicate key value is %ls. public static bool IsDuplicateKey(SqlException sex) { return (sex.Number == 2601); } } 

SqlException有一个Number属性 ,你可以检查。 重复错误的数字是2601。

 catch (SqlException e) { switch (e.Number) { case 2601: // Do something. break; default: throw; } } 

要从您的服务器获取所有SQL错误的列表,请尝试以下操作:

  SELECT * FROM sysmessages 

更新

现在可以在C#6.0中简化了

 catch (SqlException e) when (e.Number == 2601) { // Do something. } 

各种各样的。 查看数据库引擎错误的原因和解决方法

 class SqllErrorNumbers { public const int BadObject = 208; public const int DupKey = 2627; } try { ... } catch(SqlException sex) { foreach(SqlErrorCode err in sex.Errors) { switch (err.Number) { case SqlErrorNumber.BadObject:... case SqllErrorNumbers.DupKey: ... } } } 

但问题在于,在T-SQL(存储过程)中,我们需要一个良好的DAL层TRY/CATCH ,并使用exception处理和嵌套事务等模式 。 唉,一个T-SQL的TRY/CATCH块不能引发原始的错误代码,将不得不提出一个新的错误,代码高于50000.这使得客户端处理一个问题。 在SQL Server的下一个版本中,有一个新的THROW构造允许从T-SQL catch块重新引发原始exception。

使用错误代码更好,您不必parsing。

 try { } catch (SqlException exception) { if (exception.Number == 208) { } else throw; } 

如何找出应该使用的208:

 select message_id from sys.messages where text like 'Invalid object name%' 

如果你想在Sql server中遇到错误消息列表,你可以看到

 SELECT * FROM master.dbo.sysmessages 

使用MS SQL 2008,我们可以在表sys.messages中列出支持的错误消息

 SELECT * FROM sys.messages 

如果您正在寻找更好的方法来处理SQLException,那么您可以做一些事情。 首先,Spring.NET与你正在寻找的东西类似(我认为)。 以下是他们正在做的事情的链接:

http://springframework.net/docs/1.2.0/reference/html/dao.html

此外,而不是看消息,你可以检查错误代码( sqlEx.Number )。 这似乎是确定发生错误的更好方法。 唯一的问题是每个数据库提供程序返回的错误号可能不同。 如果您打算切换提供程序,您将回到按照自己的方式处理它,或者创build一个抽象层来为您转换此信息。

下面是一个使用错误代码和configuration文件翻译和本地化用户友好错误消息的人的例子:

https://web.archive.org/web/20130731181042/http://weblogs.asp.net/guys/archive/2005/05/20/408142.aspx

对于那些新手,那些从另一台机器连接到数据库时可能会抛出SQL错误的人(例如,在表单加载时),你会发现当你第一次在C#中设置一个指向SQL服务器数据库的数据表时,它会build立一个像这样的连接:

 this.Table_nameTableAdapter.Fill(this.DatabaseNameDataSet.Table_name); 

您可能需要删除此行,并将其replace为其他类似于MSDN上提到的传统连接string等。

http://www.connectionstrings.com/sql-server-2008

您可以根据严重性types进行评估。 注意要使用这个,你必须订阅OnInfoMessage

 conn.InfoMessage += OnInfoMessage; conn.FireInfoMessageEventOnUserErrors = true; 

那么你的OnInfoMessage将包含:

 foreach(SqlError err in e.Errors) { //Informational Errors if (Between(Convert.ToInt16(err.Class), 0, 10, true)) { logger.Info(err.Message); //Errors users can correct. } else if (Between(Convert.ToInt16(err.Class), 11, 16, true)) { logger.Error(err.Message); //Errors SysAdmin can correct. } else if (Between(Convert.ToInt16(err.Class), 17, 19, true)) { logger.Error(err.Message); //Fatal Errors 20+ } else { logger.Fatal(err.Message); }} 

这样你就可以评估严重程度而不是错误号码,并且更有效。 你可以在这里find关于严重性的更多信息

 private static bool Between( int num, int lower, int upper, bool inclusive = false ) { return inclusive ? lower <= num && num <= upper : lower < num && num < upper; }