将"GO"语句添加到Entity Framework迁移

Tik*_*kes 14 sql entity-framework ef-migrations

所以我有一个由Entity框架进行大量迁移的应用程序.我们希望立即获取所有迁移的脚本,并且使用该-Script标记可以正常工作.

但是......它没有GO在SQL中添加语句,给我们带来了类似的问题Alter view should be the first statement in a batch file...

我一直在搜索并手动添加Sql("GO");有关此问题的帮助,但针对整个脚本.当我再次使用包控制台管理器时,它返回一个异常.

System.Data.SqlClient.SqlException (0x80131904): Could not find stored procedure 'GO'.
Run Code Online (Sandbox Code Playgroud)

有没有办法添加这些GO标签使用时-Script的标签?如果没有,对此有什么好处?

注意:我们也尝试过多个文件,但由于我们有很多迁移,所以每次都几乎无法维护.

Col*_*lin 17

如果您尝试使用更改视图Sql("Alter View dbo.Foos As etc"),则可以通过将sql放在命令中来避免should be the first statement in a batch file错误而不添加GO语句EXEC:

Sql("EXEC('Alter View dbo.Foos As etc')")

  • @MathuSumMut这是标准的Sql。我已经省略了Sql字符串周围所需的引号。我已编辑答案以更正错误 (3认同)
  • 哇,那真的很简单而且行得通!感谢那! (2认同)

Sky*_*kyp 11

为了更改由实体框架迁移生成的SQL,您可以创建一个新的 SqlServerMigrationSqlGenerator

我们这样做是为了在迁移历史记录之前和之后添加GO语句:

public  class MigrationScriptBuilder: SqlServerMigrationSqlGenerator
{
    protected override void Generate(System.Data.Entity.Migrations.Model.InsertHistoryOperation insertHistoryOperation)
    {
        Statement("GO");

        base.Generate(insertHistoryOperation);

        Statement("GO");

    }
}
Run Code Online (Sandbox Code Playgroud)

然后添加Configuration构造函数(在MigrationsDbContext所在的项目的 文件夹中),以便它使用这个新的sql生成器:

[...]
internal sealed class Configuration : DbMigrationsConfiguration<PMA.Dal.PmaContext>
{
    public Configuration()
    {
        SetSqlGenerator("System.Data.SqlClient", new MigrationScriptBuilder());
        AutomaticMigrationsEnabled = false;
    }
[...]
Run Code Online (Sandbox Code Playgroud)

因此,现在当您使用-Script标记生成脚本时,您可以看到它insert into [__MigrationHistory]被包围GO

或者在您的实现中,SqlServerMigrationSqlGenerator您可以覆盖脚本生成的任何部分,这InsertHistoryOperation适合我们.

  • 啊我认为它在EF 6中被重命名为HistoryOperation (4认同)
  • 使用`-Script`标签时可以正常工作.我必须注释掉`SetSqlGenerator("....."行,但是当我不使用它时,因为否则我再次得到了例外.但这节省了我很多时间,因为它只是在评论一条线而不是添加`Sql("GO");`无处不在.谢谢! (2认同)

Yep*_*kai 10

结果概念存在于SqlServerMigrationSqlGenerator作为可选参数的深处Statement(sql, batchTerminator).这是基于Skyp理念的东西.它在-script模式下都可以工作.GO仅适用于不同于Skyp的操作,因为我们的需求略有不同.然后,您需要Configuration按照Skyp说明注册此类.

    public class MigrationScriptBuilder : SqlServerMigrationSqlGenerator
    {
        private string Marker = Guid.NewGuid().ToString(); //To cheat on the check null or empty of the base generator

        protected override void Generate(AlterProcedureOperation alterProcedureOperation)
        {
            SqlGo();
            base.Generate(alterProcedureOperation);
            SqlGo();
        }
        protected override void Generate(CreateProcedureOperation createProcedureOperation)
        {
            SqlGo();
            base.Generate(createProcedureOperation);
            SqlGo();
        }
        protected override void Generate(SqlOperation sqlOperation)
        {
            SqlGo();
            base.Generate(sqlOperation);
        }

        private void SqlGo()
        {
            Statement(Marker, batchTerminator: "GO");
        }

        public override IEnumerable<MigrationStatement> Generate(IEnumerable<MigrationOperation> migrationOperations, string providerManifestToken)
        {
            var result = new List<MigrationStatement>();
            var statements = base.Generate(migrationOperations, providerManifestToken);

            bool pendingBatchTerminator = false;
            foreach (var item in statements)
            {
                if(item.Sql == Marker && item.BatchTerminator == "GO")
                {
                    pendingBatchTerminator = true;
                }
                else
                {
                    if(pendingBatchTerminator)
                    {
                        item.BatchTerminator = "GO";
                        pendingBatchTerminator = false;
                    }
                    result.Add(item);
                }
            }

            return result;
        }
    }
Run Code Online (Sandbox Code Playgroud)