EF5迁移 - 删除约束时重复/重新定义的变量错误| 使用SQL GO命令的问题

bPr*_*tik 17 t-sql entity-framework ef-migrations entity-framework-5

背景:

我们有一个项目使用其中包含在长时间开发期间创建的多个(读取~60个)迁移.当然,其中一些迁移还涉及:

  • 取消约束1,2
  • 创建触发器

我们跑的时候都是独角兽和彩虹

Update-Database
Run Code Online (Sandbox Code Playgroud)

因为每个迁移都作为单独的批处理运行.但是在SQL Scripts使用时为这些迁移创建时

Update-Database -Script
Run Code Online (Sandbox Code Playgroud)

我们遇到了一些问题,如下所述:

问题1:

在多个迁移文件中删除多个约束时,EF生成的脚本会重新声明它用于删除的变量.这是因为它确保了同一个迁移文件中变量名的唯一性,但是在更改文件时,它会重置计数器,从而重叠名称.

问题2:

SQL强制执行CREATE TRIGGER始终是批处理中的第一个语句.生成脚本时,EF无视内容,Sql("CREATE TRIGGER ... ");因此不会特别对待它.因此,该语句可能出现在脚本文件的中间,并且出错.

解决方案:(或者我们想到了!)

这两个问题的常见/常识解决方案是在正确的位置插入开始/结束sql批处理.手动这样做会让我成为一个非常富有的人,所以这不是一个有效的解决方案.

相反,我们使用了@DavidSette提供技术.创建一个新的BatchSqlServerMigrationSqlGenerator继承,SqlServerMigrationSqlGenerator从中有效地覆盖dropColumnOperation,sqlOperation然后GO围绕敏感的声明强制声明:

protected override void Generate (System.Data.Entity.Migrations.Model.DropColumnOperation dropColumnOperation)
{
    base.Generate(dropColumnOperation);
    Statement("GO");
}
Run Code Online (Sandbox Code Playgroud)

Boo Boo:

此解决方案在Update-Database没有-Script标志的情况下中断运行并出现以下错

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

这是我们的自定义生成器添加的.现在我不确定为什么,但EF应该有一个很好的理由不认识GO!

更多信息:

  1. 迁移:在脚本中复制@ var0变量,删除两个约束
  2. 变量名'@number'已经声明
  3. 如何覆盖MigratorScriptingDecorator生成的SQL脚本
  4. 实体框架迁移:仅在-Script输出中包含Go语句

完整错误:

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'.
Run Code Online (Sandbox Code Playgroud)

所以基本上修复脚本打破了一个重要的命令.请帮我决定两个邪恶中哪一个更小!

Paw*_*wel 1

根据msdn

“GO 不是 Transact-SQL 语句;它是 sqlcmd 和 osql 实用程序以及 SQL Server Management Studio 代码编辑器识别的命令。”

由于您没有使用上述任何工具,而是使用 SqlCommand 类来执行 Sql 语句,因此 Sql Server(而不是 EF - 请参阅异常起源的堆栈跟踪)正在被阻塞

  • 由于“CREATE TRIGGER”和跨批次重复变量名称,因此需要“GO”。问题中对此进行了详细解释。 (2认同)