将“GO”语句添加到Entity Framework迁移

时间:2013-06-14 09:49:59

标签: sql entity-framework ef-migrations

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

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

等问题

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

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

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

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

5 个答案:

答案 0 :(得分:15)

如果您尝试使用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')")

答案 1 :(得分: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");

    }
}

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

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

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

包围

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

答案 2 :(得分:10)

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

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

答案 3 :(得分:0)

最简单的方法是在GO语句之前添加/**/。

答案 4 :(得分:-2)

只需用.Replace替换当前语句(&#34; GO&#34;,&#34;&#34;);