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文件翻译和本地化用户友好错误消息的人的例子:
对于那些新手,那些从另一台机器连接到数据库时可能会抛出SQL错误的人(例如,在表单加载时),你会发现当你第一次在C#中设置一个指向SQL服务器数据库的数据表时,它会build立一个像这样的连接:
this.Table_nameTableAdapter.Fill(this.DatabaseNameDataSet.Table_name);
您可能需要删除此行,并将其replace为其他类似于MSDN上提到的传统连接string等。
您可以根据严重性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; }