entity-framework - remove - update database entity framework c#
Migraciones de EF5-Error de variable duplicada/redefinida al eliminar restricciones | Problema con el uso del comando SQL GO (4)
Fondo:
Tenemos un proyecto que utiliza ef-migrations contienen múltiples ef-migrations (de lectura ~ 60) creadas durante un largo período de desarrollo. Naturalmente, algunas de estas migraciones también involucran:
Todo es unicornios y arco iris cuando corremos.
Update-Database
porque cada migración se ejecuta como un lote separado. Pero al crear SQL Scripts
para estas migraciones usando
Update-Database -Script
encontramos algunos problemas como se describe a continuación:
Problema 1:
Cuando se eliminan varias restricciones en varios archivos de migración, el script generado por EF tiende a volver a declarar las variables que utiliza para eliminar. Esto se debe a que garantiza la exclusividad de los nombres de las variables dentro del mismo archivo de migración, pero al cambiar el archivo, restablece el contador, por lo que se superponen los nombres.
Problema 2:
SQL exige que CREATE TRIGGER
sea siempre la primera declaración de un lote. Cuando se genera el script, EF es ajeno a los contenidos de Sql("CREATE TRIGGER ... ");
Y por lo tanto no lo trata especialmente. Por lo tanto, la declaración puede aparecer justo en el medio de un archivo de script, y se produce un error.
Solución: (o eso creíamos!)
Una solución común / de sentido común para los dos problemas es insertar Begin / End the sql batch en los lugares correctos. Hacer esto manualmente me haría un hombre muy rico, por lo que no es una solución eficiente.
En su lugar, utilizamos la técnica proporcionada por @DavidSette . Crear un nuevo BatchSqlServerMigrationSqlGenerator
heredado de SqlServerMigrationSqlGenerator
que anula efectivamente dropColumnOperation
y sqlOperation
y luego forzando una instrucción GO
torno a los sensibles como tales:
protected override void Generate (System.Data.Entity.Migrations.Model.DropColumnOperation dropColumnOperation)
{
base.Generate(dropColumnOperation);
Statement("GO");
}
Boo Boo:
Esta solución rompe la ejecución Update-Database
sin el indicador -Script
con el siguiente error:
System.Data.SqlClient.SqlException (0x80131904): Could not find stored procedure ''GO''.
Lo cual fue agregado por nuestro generador personalizado. Ahora no estoy seguro de por qué, ¡pero debería haber una buena razón para que EF no reconozca GO
!
Más información:
- 1
- 2
- ¿Cómo puedo anular los scripts SQL generados por MigratorScriptingDecorator?
- Migraciones de Entity Framework: incluye la instrucción Go solo en la salida de código
Error 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''.
Así que básicamente arreglar los scripts rompe un comando esencial. ¡Por favor, ayúdame a decidir cuál es el menor de los dos males!
Después experimenté el problema de primera mano .
Decidimos crear migraciones más pequeñas. Si el cambio fue lo suficientemente grande como para requerir un comando GO, entonces el desarrollador estaba intentando cambiar demasiado en una migración. Desafortunadamente, la única forma de controlar lo que implica una migración es comentar los cambios.
También me pregunté por qué quería tanto el guión. No es como si no confiara en EF para realizar la migración correctamente (siempre que lo probé primero). Lo ideal sería que nunca y (afortunadamente) todavía no haya una razón para modificarlo. Solo lo he visto unas cuantas veces cuando comencé a usar EF Code First.
No me gusta esta respuesta, pero no creo que tenga otro propósito que no sea la depuración de una migración para Entity Framework Code First.
Pongo un Sql ("- <GO>"); Al final de cada migración. Esto funciona bien como una migración aplicada y cuando guión el SQL, simplemente hago una búsqueda y reemplazo en "- <GO>" a "IR". Un poco manual pero funciona para mi. Puedes poner Sql ("- <GO>"); alrededor de sus declaraciones de activación de creación.
Según msdn
"GO no es una declaración Transact-SQL; es un comando reconocido por las utilidades sqlcmd y osql y el editor de código de SQL Server Management Studio".
Ya que no está utilizando ninguna de las herramientas anteriores, sino la clase SqlCommand para ejecutar su sentencia de SQL Server Sql Server (y no EF - ver el seguimiento de pila donde se originó la excepción) se está atragantando
Solo borra todas las repeticiones de esta línea:
DECLARE @var0 nvarchar(128)
Sólo la primera declaración es suficiente. ¡Tu guión funcionará sin problemas! :)