17

Entity Frameworkの移行計画の一環として、データの移動をデバッグするために、-Scriptパラメーターを使用してスクリプトを生成することがよくありました。

次に、このスクリプトをQuery Analyzerに移動し、トランザクションでラップして、手動でテストすることができます。

スクリプトを正しく実行するためにGoステートメントが必要な状況に遭遇しました。Goを適切な場所に出力するために、次のコードが移行に追加されました。

Sql("GO");

これにより、-Scriptが使用されている場合、適切な位置にGOステートメントが追加されます。ただし、-Scriptを使用しない場合。例外が発生します...

System.Data.SqlClient.SqlException (0x80131904): Could not find stored procedure 'GO'.

スクリプトにGoコマンドを追加する安全な方法はありますか?

4

5 に答える 5

15

私は最近まったく同じ状況に遭遇しました。私のEFコードの移行では、新しいテーブルまたは列が導入されることがよくあります。次に、新しいテーブル/列を参照することがある移行に、Sql(...)を使用したデータ移行も配置します。ご指摘のとおり、EFコードの移行として実行すると、各ステートメントは個別のバッチとしてDBに発行されているように見えるため、問題はありません。ただし、本番デプロイメントの制約を満たすために、スプリントからの一連のコード移行を(-Scriptを使用して)単一のスクリプトに変換し、デプロイメントチームに単一の集約SQLスクリプト移行を提示します。ご指摘のとおり、このスクリプトファイルは、単一のコード移行から単一のT SQLバッチを処理しようとするために失敗することがあります。この場合、後のステートメントは、バッチの前半でのみ定義された構造を参照しようとします。

私はこれを軽減するために今のところ取った2つのアプローチのどちらも特に好きではありませんが、ここにあります:

a。当時考えていた場合は、コードの移行を2つの移行に分割して、スクリプト化されたときに2つ(またはそれ以上)の別々のバッチになるようにします。コード移行の開発中にこれが必要であるというフィードバックがないため、これは好きではありません。したがって、エラーが発生しやすいようです。

b。集約スクリプトを生成するとき、それらをスクラッチDBに対して実行して証明し、そのスクリプトの必要に応じて手動で「GO」ステートメントを挿入することになります。これは、戻って実行しなければならない厄介なプロセスであり、コード移行を100%反映していない-Script出力になります。

EF Code Migrationsのソースコードを詳しく調べて、「GO」がストアドプロシージャとして解釈される理由を理解できるかどうか、およびソースコードにそれを回避するディレクティブを提供します。

于 2012-09-19T12:51:17.430 に答える
9
internal sealed class Configuration : DbMigrationsConfiguration<Context>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        const string providerInvariantName = "System.Data.SqlClient";
        SetSqlGenerator(providerInvariantName, new BatchingMigrationSqlGenerator(GetSqlGenerator(providerInvariantName)));
    }

    protected override void Seed(Context context)
    {
    }

}

internal class BatchingMigrationSqlGenerator : MigrationSqlGenerator
{
    private readonly MigrationSqlGenerator migrationSqlGenerator;

    public BatchingMigrationSqlGenerator(MigrationSqlGenerator migrationSqlGenerator)
    {
        this.migrationSqlGenerator = migrationSqlGenerator;
    }

    public override IEnumerable<MigrationStatement> Generate(IEnumerable<MigrationOperation> migrationOperations, string providerManifestToken)
    {
        var migrationStatements = migrationSqlGenerator.Generate(migrationOperations, providerManifestToken).ToArray();
        foreach (var migrationStatement in migrationStatements)
        {
            migrationStatement.BatchTerminator = "GO";
        }
        return migrationStatements;
    }
}
于 2015-07-02T10:10:06.840 に答える
2

パラメータを使用して、または使用Configurationせずに移行を実行すると、2つの異なるクラスを使用することになりました。-Script私のConfigurationクラスの1つでは、ステートメントMigrationSqlGeneratorを追加するカスタム実装でラップします。GO

于 2013-02-14T07:41:56.893 に答える
0

私が使用した:

public class MigrationScriptBuilder : SqlServerMigrationSqlGenerator
{
#if !DEBUG
    protected override void Generate(System.Data.Entity.Migrations.Model.SqlOperation sqlOperation)
    {
        Statement("GO");

        base.Generate(sqlOperation);

        Statement("GO");
    }
#endif
}

したがって、デバッグ時にクラッシュすることはありません。そして、リリースモードからスクリプトを作成します。

于 2015-11-20T12:35:40.233 に答える
0

これは私のために働いています:

public class MigrationScriptBuilder : SqlServerMigrationSqlGenerator
{
    public override IEnumerable<MigrationStatement> Generate(IEnumerable<MigrationOperation> migrationOperations, string providerManifestToken)
    {
        var statements = base.Generate(migrationOperations, providerManifestToken);

        statements = statements.SelectMany(s => new[] {
            s,
            new MigrationStatement
            {
                Sql = "GO"
            }
        }).ToList();

        return statements;
    }
}

(他の回答に見られるように)DbContext構成のこの種のメソッドで使用できるもの(移行プロセスフロー):

    public Configuration()
    {
        SetSqlGenerator("System.Data.SqlClient", new MigrationScriptBuilder());
    }
于 2017-08-31T06:10:21.500 に答える