ADO.NETおよびExecutENONQUERY:DDLの使用方法
-
29-09-2019 - |
質問
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
存在しない。実行する前に解析して検証するようです。
管理スタジオで全体を実行するとき、私は置くことができます 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);
}
}
解決
各バッチを個別に実行する必要があります。特に、複数のバッチ(「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
}
他のヒント
それを行うためにumpteen ormライブラリのいずれかを使用していませんか?良い :-)
構造変更を実行するスクリプトを実行するときに完全に安全であることは、SQLClientではなくSMOを使用し、MARSが接続文字列を介してオンになっていないことを確認します(SMOは通常、それがとにかく不満を言います)。探す ServerConnection クラスとexecutenOnquery-もちろん別のdll :-)
diffは、SMO DLLがスクリプトをSQLに配置するため、SSMまたはISQL CMDラインを介して実行するのと同等のものであることです。 GO-Sのスライスは、別のグリッチに遭遇するたびにはるかに大きなスキャンに成長することになります(そのように、GOはマルチラインコメントの途中にあります。複数の使用ステートメントがあります。 sqlclientに接続されています - oops :-)。私は、私が継承したコードベースでそのようなことを殺したところです(火星と競合するより複雑なスクリプトが生産コードに適しているが、管理者のものではない)。