在C#中使用SQL Server值得一说:
IF COL_LENGTH('MyTable','MyColumn') IS NULL
BEGIN
ALTER TABLE MyTable ADD MyColumn INT
END
因为我可以更容易地抓住电话:
try
{
Db.ExecuteNonQuery("ALTER TABLE MyTable ADD MyColumn INT");
}
catch(Exception)
{
}
然后让它一直失败(除了在旧数据库上运行时)... 还是顽皮/慢/等?
答案 0 :(得分:9)
例外应该是“例外”,例如规则的例外情况。 您是否计划运行此代码,并且有90%的时间,该列存在?
那不是“例外”。
不要将异常捕获用作正常的逻辑流程。
以下是比我更聪明的人的更多指示:
http://blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx
“不要将异常用于正常的控制流程。”
这是我典型的幂等添加列tsql。
IF EXISTS ( SELECT TABLE_SCHEMA , TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Categories' and TABLE_SCHEMA = 'dbo' )
BEGIN
IF NOT EXISTS
(
SELECT *
FROM [INFORMATION_SCHEMA].[COLUMNS]
WHERE
TABLE_NAME = 'Categories'
AND TABLE_SCHEMA = 'dbo'
AND COLUMN_NAME = 'CategoryName'
)
BEGIN
print 'Adding the column dbo.Categories.*CategoryName*'
ALTER TABLE [dbo].[Categories] ADD [CategoryName] nvarchar(15) NOT NULL
END
ELSE
BEGIN
print 'The column dbo.Categories.*CategoryName* already exists.'
END
END
答案 1 :(得分:7)
只是不要以这种方式捕获Exception
异常:你永远不会知道它是否被抛出:
如果只想创建一个列,如果它尚不存在,请在添加之前编写检查列存在的SQL。
答案 2 :(得分:2)
在这种情况下,速度真的很重要吗?您多久更新一次数据库?
但是,你真的确定你想要默默地吃掉所有例外吗?问题可能是您没有DDL(修改数据库)权限或列存在但具有不同的列类型。
答案 3 :(得分:0)
在脚本中执行此类检查非常标准,因为脚本可能需要多次运行。例如,可能会向其添加其他表更改。如果有人必须重新运行它,您不希望脚本导致错误。
正如其他人所指出的那样,应该为真正特殊情况保留例外情况。
但是在C#代码中执行此操作还有一个问题:您正在将数据库维护内容混合到(大概)您的应用程序代码中。如果您遵循separation of concerns原则,那么您的代码将更具可读性和可维护性。
答案 4 :(得分:0)
你的C#代码流只是后端的一个浅垫片,真正的工作正在发生。因此,出现了明显的问题:
原因包括但不限于:
你愿意默默地吞下并使异常沉默,因为你只能想到一个可能的失败原因。在处理数据库时,你总是需要认真记录,否则你只是在脚下射击。
关于SEH是否便宜还存在很长时间的争论,但在数据库中谈论DDL时,这完全超出了这一点。 您正在请求对象的SCH-M锁定,因此会阻止所有人,直到您获得它为止。即使您的DDL抛出并处理异常,在等待授予超级锁定时,您已经将吞吐量降低到0(零)。你可能已经等了小时,你知道......