我有一个简单的country表,使用identity列作为主键。还有一些列用于包含2个字母和3个字母的ISO-3166国家/地区代码。这些列中的每一列都被定义为唯一索引。
在插入/更新时,我只想通知用户输入的ISO代码是否已在使用中。我依赖于数据库异常来触发这个过程。我不想用技术细节让用户不知所措。我只想告诉他输入的ISO值不能使用。
下面是我编写的Update存储过程中的T-SQL。它似乎很长,而且随着应用程序的增长和变化,它很容易出现将来的bug和/或持续的维护。有没有更好或更简单的方法?我可能对.net有点不熟悉,但我觉得这会更容易。
BEGIN TRY
UPDATE [Country] SET [CountryName] = @CountryName, [CountryISO] = @CountryISO, [CountryISO3] = @CountryISO3, [UpdateDate] = @updateDate WHERE (([CountryID] = @CountryID) AND ([RowVersion] = @Original_RowVersion));
END TRY
BEGIN CATCH
DECLARE @ErrSeverity int, @ErrNumber int, @ErrLine int
DECLARE @ErrMsg nvarchar(4000)
SELECT @ErrSeverity = ERROR_SEVERITY(), @ErrNumber = ERROR_NUMBER(),@ErrState = ERROR_STATE(),
@ErrMsg =
CASE WHEN ERROR_NUMBER() = 2601
THEN
CASE
WHEN ISNULL(CHARINDEX('IX_COUNTRYISO3', ERROR_MESSAGE()), 0) > 0
THEN 'The 3 letter ISO-3166 value entered is already in use. Please enter a unique 3 letter ISO-3166 value.'
WHEN ISNULL(CHARINDEX('IX_COUNTRYISO', ERROR_MESSAGE()), 0) > 0
THEN 'The 2 letter ISO-3166 value entered is already in use. Please enter a unique 2 letter ISO-3166 value.'
ELSE
ERROR_MESSAGE() + '(SQL ErrNo: ' + CONVERT(varchar(50), ERROR_NUMBER()) + ')'
END
ELSE
ERROR_MESSAGE() + '(SQL ErrNo: ' + CONVERT(varchar(50), ERROR_NUMBER()) + ')'
END;
RAISERROR(@ErrMsg, @ErrSeverity, @ErrState)
END CATCH我的解决方案可行吗?
在插入和更新StoredProcs之间共享此异常代码的最佳方式是什么?
我想我本质上是在要求代码审查。
非常感谢你,迈克
发布于 2010-01-18 04:54:51
我同意,这样的代码将成为令人头疼的维护问题。代码本身没有问题,只是问题被发现得太晚了。
唯一约束/索引是“最后一道防线”,至少在我的世界里是这样。如果您想提供良好的用户体验,您不能等到数据已经提交到数据库。您应该在UI级别主动检查重复项,并警告用户即将提交重复条目(如果不允许重复键,则禁用提交)。
如果最终提交了重复的键,这实质上说明了应用程序逻辑中的错误,所以数据库发出“类似数据库”的错误消息是可以接受的,您不需要试图美化它。应用程序应该尽可能优雅地处理此类错误,就像处理任何其他意外异常一样。
如果您只是简单地询问是否有一种方法可以在T-SQL中模块化这种功能……我不这样认为。无论如何,如果没有动态SQL的糟糕混乱,就不会有这样的问题。
SQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdate-刚刚看到了对另一个答案的评论,如果你想在C#中重新获得错误号,那就足够简单了:
const int SqlDuplicateKeyError = 2601;
try
{
db.Update(record);
}
catch (SqlException ex)
{
switch (ex.Number)
{
case SqlDuplicateKeyError:
// Custom error handling here
default:
throw;
}
}发布于 2010-01-18 04:44:24
就我个人而言,我认为简单地给你的unqique约束/索引起一个合理而冗长的名字会比这更好。
如果用户直接与数据库交互,那么他们至少应该有一点IT知识。
如果用户通过自定义前端进行交互,那么您应该在前端实现错误处理。
要在前端捕获它,请参阅此link,这是一个基本的示例(可能充满错误)示例……
Catch (SqlExpcetion ex)
{
if (e.Number == 2061 && ex.Message.Contains("IX_COUNTRYISO3")
{
MessageBox.Show("The 3 letter ISO-3166 value entered is already in use. Please enter a unique 3 letter ISO-3166 value.");
}
else
{
MessageBox.Show(String.Format("Error ({0}):{1}",ex.Number,ex.Message)
}
}
Catch (Exception ex)
{
MessageBox.Show(ex);
}https://stackoverflow.com/questions/2082529
复制相似问题