EF 4.3.1迁移播种工作不正常(EF 4.3.1 Migrations Seeding not

2019-09-17 01:49发布

我使用EF 4.3.1迁移和我有,我有以下的代码配置类:

internal sealed class Configuration : DbMigrationsConfiguration<DbContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(PayByPhoneDbContext context)
    {
        context.Roles.AddOrUpdate(r => r.Name, new Role { Name = "A" }, new Role { Name = "B" });
        context.Administrators.AddOrUpdate(a => a.Email, new Administrator { Email = "a@a.com" Name = "A", Role = context.Roles.Local.SingleOrDefault(role => role.Name == "A") });
    }
}

现在,当我运行迁移命令(的MSBuild脚本的一部分),当数据块不存在,创建表和播种发生如预期。 但是,当我现有的数据库上运行迁移命令不带任何迁移,所有数据已经​​播种(更新时需要发生的,而不是插入)我得到一个错误上运行的迁移命令:

无待明确的迁移。

运行种子法。

System.Data.Entity.Infrastructure.DbUpdateException:更新条目中出现了错误。 详情请参阅内部异常。 ---> System.Data.UpdateException:更新条目中出现了错误。 详情请参阅内部异常。 ---> System.Data.SqlClient.SqlException:UPDATE语句冲突与外键约束“FK_Administrators_Roles_RoleId”。 冲突发生于数据库“xxxDB”,表“dbo.Roles”,列“ID”。

该语句已终止。

堆栈跟踪:

at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary`2 identifierValues, List`1 generatedValues)
   at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)
   --- End of inner exception stack trace ---
   at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)
   at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)
   at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
   at System.Data.Entity.Internal.InternalContext.SaveChanges()
   --- End of inner exception stack trace ---
   at System.Data.Entity.Internal.InternalContext.SaveChanges()
   at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
   at System.Data.Entity.DbContext.SaveChanges()
   at System.Data.Entity.Migrations.DbMigrator.SeedDatabase()
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.SeedDatabase()
   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()

执行时,运行SQL Server Profiler中,我发现了错误发生:

exec sp_executesql N'update [dbo].[Administrators]
set [RoleId] = @0
where ([Id] = @1)
',N'@0 int,@1 bigint',@0=0,@1=1

什么是种子在种子法外键数据的正确方法?

Answer 1:

AddOrUpdate将重置你不指定为空(或零int的情况下)列。

我的理解是,这种行为(其中的方式是可怕的)并不适用于它识别为按键或自动增量列,但显然它是在你的情况。

我的建议是做一个检查,以确保该角色不存在于数据库中,然后做一个标准的add(),如果它没有。

我这样做是为我所有的种子数据,因为你永远不知道什么时候你以后可能会用于更新您种子数据提供一个接口,而你不想种子()方法来覆盖在该等情况下更改。

也请记住,如果你选择使用MigrateDatabaseToLatestVersion数据库初始化,然后种子()每次都会触发您的应用程序重新启动(DLL部署的web.config更新等)。

这是最好的种子()方法防守编码。

更新:朱莉·勒曼具有良好的博客文章有关此问题。



文章来源: EF 4.3.1 Migrations Seeding not working as expected