ADO.NET and ExecuteNonQuery: how to use DDL

﹥>﹥吖頭↗ 提交于 2019-12-12 01:18:31

问题


I execute SQL scripts to change the database schema. It looks something like this:

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

Additionally, the commands are executed within a transaction.

The scrip looks like this:

Alter Table [TableName]
ADD [NewColumn] bigint NULL

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

I get an error, because NewColumn does not exist. It seems to parse and validate it before it is executed.

When I execute the whole stuff in the Management Studio, I can put GO between the statements, then it works. When I put GO into the script, ADO.NET complains (Incorrect syntax near 'GO').

I could split the script into separate scripts and execute it in separate commands, this would be hard to handle. I could split it on every GO, parsing the script myself. I just think that there should be a better solution and that I didn't understand something. How should scripts like this be executed?


My implementation if anyone is interested in, according to John Saunders' answer:

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);
    }
}

回答1:


You have to run each batch separately. In particular, to run a script that may contain multiple batches ("GO" keywords), you have to split the script on the "GO" keywords.

Not Tested:

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
}



回答2:


Not using one of umpteen ORM libraries to do it ? Good :-)

To be completely safe when running scripts that do structural changes use SMO rather than SqlClient and make sure MARS is not turned on via connection string (SMO will normally complain if it is anyway). Look for ServerConnection class and ExecuteNonQuery - different DLL of course :-)

The diff is that SMO dll pases the script as-is to SQL so it's genuine equivalent of running it in SSMS or via isql cmd line. Slicing on GO-s ends up growing into much bigger scanning every time you encounter another glitch (like that GO can be in the middle of a multi-line comment, there can be multiple USE statements, a script can be dropping the very DB that SqlCLient connected to - oops :-). I just killed one such thing in the codebase I inherited (after more complex scripts conflicted with MARS and MARS is good for production code but not for admin stuff).



来源:https://stackoverflow.com/questions/3102768/ado-net-and-executenonquery-how-to-use-ddl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!