0

在 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)
{
}

并且让如果一直失败(除非在旧数据库上运行)......或者是顽皮/慢/等等?

4

5 回答 5

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
于 2013-03-11T13:16:21.397 回答
7

只是不要以Exception这种方式捕获异常:您永远不会知道它是否被抛出:

  • 因为表不存在
  • 因为该列已经存在
  • 因为连接字符串错误
  • 因为网络错误
  • 任何其他原因

如果您只想在列不存在时创建它,请在添加之前编写检查列是否存在的 SQL。

于 2013-03-11T13:16:02.847 回答
2

在这种情况下,速度真的很重要吗?您多久更新一次数据库?

但是,您真的确定要默默地吃掉所有异常吗?问题可能是您没有 DDL(修改数据库)权限,或者该列存在但具有不同的列类型。

于 2013-03-11T13:16:36.857 回答
0

在您的脚本中执行此类检查是非常标准的,因为该脚本可能需要多次运行。例如,其他表更改可能会添加到其中。如果有人必须重新运行它,您不希望您的脚本导致错误。

正如其他人所指出的,应为真正的例外情况保留例外。

但是在您的 C# 代码中执行此操作还有一个额外的问题:您将数据库维护内容混合到(可能)您的应用程序代码中。如果您遵循关注点分离的原则,您的代码将更具可读性和可维护性。

于 2013-03-11T13:26:46.683 回答
0

您的 C# 代码流只是后端的一个浅垫片,真正的工作发生在这里。因此,出现了明显的问题:

为什么会引发异常?

原因包括但不限于:

  • 您无权更改表格
  • 您尝试获取表上的 SCH-M 锁时超时
  • 新列触发日志空间不足的数据大小操作
  • 自定义DDL 触发器阻止执行
  • 基于策略的声明性管理规则阻止执行
  • IO 子系统刚刚崩溃,数据库处于脱机状态
  • 该列已经存在(这似乎是您想到的唯一情况)

你愿意默默地吞下和沉默例外,因为你只能想到一个可能的失败原因。在处理数据库时,您总是需要认真的日志记录,否则您只会自找麻烦。

例外是免费的吗?

SEH 是否便宜存在很长时间的争论,但这完全超出了谈论数据库中的 DDL 的意义。您正在请求一个对象上的 SCH-M 锁定,因此将阻止所有人,直到您获得它。即使您的 DDL 抛出并且您处理了异常,在您等待超级锁被授予时,您已经将吞吐量降至 0(零)。你可能已经等了好几个小时了,你知道...

于 2013-03-11T13:33:57.317 回答