我执行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);
}
}
答案 0 :(得分:2)
没有使用一个无数的ORM库来做到这一点?好的: - )
在运行进行结构更改的脚本时要完全安全,请使用SMO而不是SqlClient,并确保MARS未通过连接字符串打开(如果无论如何,SMO通常会抱怨)。查找 ServerConnection 类和ExecuteNonQuery - 当然是不同的DLL: - )
差异在于SMO dll将脚本按原样固定到SQL,因此它真正等同于在SSMS中运行它或通过isql cmd行运行它。每次遇到另一个小故障时,GO-s上的切片最终会变得更大,因为GO可以在多行注释的中间,可以有多个USE语句,一个脚本可以删除那个DB SqlCLient连接到 - oops :-)。我刚刚在我继承的代码库中杀死了一个这样的东西(在与MARS和MARS冲突的更复杂的脚本对生产代码有利但对管理员的东西不利之前)。
答案 1 :(得分: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
}