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

问题描述 投票:14回答:4

所以我有一个由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标签?如果没有,对此有什么好处?

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

sql entity-framework ef-migrations
4个回答
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适合我们。


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')")


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

-2
投票

只需用.Replace(“GO”,“”)替换当前语句;

© www.soinside.com 2019 - 2024. All rights reserved.