Migrações EF5 - Bug de variável duplicado / redefinido ao eliminar restrições | Problema com o uso do comando SQL GO

Fundo:

Nós temos um projeto que usaef-migrações contendo migrações múltiplas (leitura ~ 60) criadas durante um longo período de desenvolvimento. Naturalmente, algumas dessas migrações também envolvem:

soltando restrições1,2criando gatilhos

Tudo é unicórnios e arco-íris quando corremos

Update-Database

porque cada migração é executada como um lote separado. Mas ao criarSQL Scripts para essas migrações usando

Update-Database -Script

Encontramos alguns problemas, conforme descrito abaixo:

Problema 1:

Ao eliminar várias restrições em vários arquivos de migração, o script gerado pelo EF tende a declarar novamente as variáveis ​​que ele usa para descartar. Isso ocorre porque garante a exclusividade dos nomes das variáveis ​​dentro do mesmo arquivo de migração, mas na alteração do arquivo, ele redefine o contador, sobrepondo, assim, os nomes.

Problema 2:

SQL impõe queCREATE TRIGGER é sempre a primeira instrução em um lote. Quando o script é gerado, EF fica alheio ao conteúdo deSql("CREATE TRIGGER ... "); e, portanto, não trata nada de especial. Assim, a declaração pode aparecer no meio de um arquivo de script e com erro.

Solução: (ou assim pensamos!)

Uma solução comum / de senso comum para os dois problemas é inserir Begin / End the sql batch nos lugares certos. Fazer isso manualmente me tornaria um homem muito rico, então essa não é uma solução eficiente.

Em vez disso, usamos otécnica fornecida por @DavidSette. Criando um novoBatchSqlServerMigrationSqlGenerator herdando deSqlServerMigrationSqlGenerator que efetivamente substituidropColumnOperation esqlOperation e depois forçando umGO declaração em torno dos sensíveis como tal:

protected override void Generate (System.Data.Entity.Migrations.Model.DropColumnOperation dropColumnOperation)
{
    base.Generate(dropColumnOperation);
    Statement("GO");
}
Boo Boo:

Esta solução quebra correndoUpdate-Database sem o-Script sinalizador com o seguinte erro:

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

Que foi adicionado pelo nosso gerador personalizado. Agora eu não tenho certeza do porquê, mas deve haver uma boa razão para a EF não reconhecerGO!

Mais informações:

Migrações: Variáveis ​​duplicadas @ var0 no script que solta duas restriçõesO nome da variável '@number' já foi declaradoComo posso substituir scripts SQL gerados pelo MigratorScriptingDecoratorMigrações de estrutura de entidades: Incluindo a instrução Go somente na saída de -Script

Erro completo:

Applying code-based migration: 201205181406363_AddTriggerForOverlap.
GO
System.Data.SqlClient.SqlException (0x80131904): Could not find stored procedure 'GO'.
    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
    at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
    at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout)
    at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
    at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
    at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
    at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
    at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements)
    at System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable`1 migrationStatements)
    at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable`1 operations, Boolean downgrading, Boolean auto)
    at System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration)
    at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ApplyMigration(DbMigration migration, DbMigration lastMigration)
    at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
    at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
    at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
    at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
    at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore()
    at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()
ClientConnectionId:ac53af4b-1f9b-4849-a0da-9eb33b836caf
Could not find stored procedure 'GO'.

Então, basicamente, consertar os scripts quebra um comando essencial. Por favor me ajude a decidir qual é o menor dos dois males!

questionAnswers(4)

yourAnswerToTheQuestion