C# 尝试向SQL Server数据库添加一列并捕获异常是否可以?

C# 尝试向SQL Server数据库添加一列并捕获异常是否可以?,c#,sql,sql-server,C#,Sql,Sql Server,在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) { } 并且让if一直失败(在旧数据库上运行时除外)。。。

在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)
{
}
并且让if一直失败(在旧数据库上运行时除外)。。。
或者是顽皮/缓慢/等等?

只是不要用这种方式捕捉
异常
异常:你永远不会知道它是否被抛出:

  • 因为表不存在
  • 因为该列已经存在
  • 因为连接字符串是错误的
  • 因为网络错误
  • 还有其他原因吗
如果只想在列不存在的情况下创建列,请在添加列之前编写检查该列是否存在的SQL。

异常应为“异常”,如规则中的异常。 您是否计划运行此代码,并且90%的时间该列存在

那么这就不是“例外”

不要将异常捕获用作正常逻辑流。

以下是一些比我聪明的人的建议:

“不要对正常控制流使用异常。”


下面是我典型的幂等元加法列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

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


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

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

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

但是在C代码中这样做还有一个额外的问题:你把数据库维护的东西混入(大概)你的应用程序代码中。如果遵循以下原则,代码的可读性和可维护性将大大提高。

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

为什么会出现异常? 原因包括但不限于:

  • 您没有更改表的权限
  • 您尝试获取表上的SCH-M锁时超时
  • 新列将触发日志空间不足的事件
  • 一个习惯阻止执行
  • 规则禁止执行
  • IO子系统刚刚崩溃,数据库处于脱机状态
  • 该列已经存在(这似乎是您想到的唯一情况)
你愿意默默地吞咽和沉默例外,因为你只能考虑一个可能的失败原因。在处理数据库时,您总是需要认真地记录日志,否则您就是在自食其果

这个例外是免费的吗?
关于SEH是否便宜还有很长的争论,但这完全超出了在数据库中谈论DDL的范围您正在请求对象上的SCH-M锁,因此将阻止所有人,直到您得到它。即使您的DDL抛出并处理异常,在等待uber锁被授予时,您已经将吞吐量降至0(0)。你可能已经等了好几个小时了,你知道

IMO选项1是正确的。只要有可能,您的脚本应该进行自己的检查。IMO选项#1更好,但您仍然没有检查列的存在性。如果不存在,最好使用
形式的查询(从sys.columns中选择*。
@DanPuzey,有一个答案与您的答案不一致169次…!@noelicus:以前从未遇到过!我确实认为它不太可读,但似乎您的语法是有效的。抱歉!啊,很高兴知道!谢谢您这么说。哇!这不是有点冗长吗?冗长只是旁观者的眼睛。10几年后,有人可以查看我的代码,并确切地知道发生了什么。我的目标是编写可维护的代码,而不是简洁的代码。但这里有很多灰色地带。这很公平!想想看,我的意思是:我的问题中引用的小得多的代码有什么问题吗?通过将不同的代码放入你的回答意味着原来的例子还不够好!有不同的方法可以剥猫皮。我的回答(不仅)针对你,而是针对整个开发人员社区。我的回答基于ANSI标准,因此应该适用于所有符合ANSI标准的数据库。(可能除了数据类型)。当然。我意识到了这一点(这是给大家的)。很高兴知道它是通用的。谢谢你的回答。非常感谢,和其他人一样:)如果几年后我有大量的专栏要更新,我想速度可能很重要?我只是好奇,真的!