0

我执行 SQL 脚本来更改数据库架构。它看起来像这样:

using (var command = connection.CreateCommand())
{
    command.CommandText = script;
    command.ExecuteNonQuery();
}

此外,命令在事务中执行。

脚本如下所示:

Alter Table [TableName]
ADD [NewColumn] bigint NULL

Update [TableName]
SET [NewColumn] = (SELECT somevalue FROM anothertable)

我得到一个错误,因为NewColumn不存在。它似乎在执行之前对其进行解析和验证。

当我在 Management Studio 中执行所有内容时,我可以GO在语句之间放置,然后它就可以工作了。当我GO输入脚本时,ADO.NET 抱怨('GO' 附近的语法不正确)。

我可以将脚本拆分为单独的脚本并在单独的命令中执行,这将很难处理。我可以在每个 上拆分它GO,自己解析脚本。我只是认为应该有一个更好的解决方案,我不明白一些事情。应该如何执行这样的脚本?


根据约翰桑德斯的回答,如果有人感兴趣,我的实现:

List<string> lines = new List<string>();
while (!textStreamReader.EndOfStream)
{
    string line = textStreamReader.ReadLine();
    if (line.Trim().ToLower() == "go" || textStreamReader.EndOfStream)
    {
        ExecuteCommand(
            string.Join(Environment.NewLine, lines.ToArray()));

        lines.Clear();
    }
    else
    {
        lines.Add(line);
    }
}
4

2 回答 2

2

不使用无数 ORM 库之一来做到这一点?好的 :-)

为了在运行进行结构更改的脚本时完全安全,请使用 SMO 而不是 SqlClient,并确保 MARS 未通过连接字符串打开(无论如何,SMO 通常会抱怨)。寻找ServerConnection类和 ExecuteNonQuery - 当然是不同的 DLL :-)

不同之处在于 SMO dll 将脚本按原样传递给 SQL,因此它真正等同于在 SSMS 中或通过 isql cmd 行运行它。每次遇到另一个故障时,对 GO-s 的切片最终会变成更大的扫描(例如,GO 可能位于多行注释的中间,可能有多个 USE 语句,脚本可能会删除SqlCLient 连接到 - 哎呀 :-)。我刚刚在我继承的代码库中杀死了一个这样的东西(在更复杂的脚本与 MARS 冲突之后,MARS 对生产代码有好处,但对管理内容没有好处)。

于 2010-08-14T22:18:33.770 回答
1

您必须分别运行每个批次。特别是,要运行可能包含多个批处理(“GO”关键字)的脚本,您必须在“GO”关键字上拆分脚本。

未测试:

string script = File.ReadAllText("script.sql");
string[] batches = script.Split(new [] {"GO"+Environment.NewLine}, StringSplitOptions.None);
foreach (string batch in batches)
{
    // run ExecuteNonQuery on the batch
}
于 2010-06-23T14:59:31.577 回答