2012-05-06 54 views
4

我使用EF 4.3.1遷移和我有,我有以下的代碼配置類: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 = "[email protected]" Name = "A", Role = context.Roles.Local.SingleOrDefault(role => role.Name == "A") }); 
    } 
} 

現在,當我運行遷移命令(當DB不存在時,創建表並按預期發生播種。但是,當我現有的數據庫上運行遷移命令不帶任何遷移和所有數據都已經播種(當更新需要發生的,而不是插入)我上運行的遷移命令得到一個錯誤:

無待明確的遷移。

運行種子法。

System.Data.Entity.Infrastructure.DbUpdateException:更新條目時發生錯誤 。詳情請參閱內部例外。 ---> System.Data.UpdateException:更新 條目時發生錯誤。詳情請參閱內部例外。 ---> System.Data.SqlClient.SqlException:UPDATE語句與FOREIGN KEY約束「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 

什麼是種子在種子法外鍵數據的正確方法?

+1

你是否'context.Roles.Local.SingleOrDefault(角色=> role.Name == 「A」)'返回正確的角色,而不是'null'? – Slauma

+0

在Nuget控制檯或命令提示符下運行時(使用migrate.exe時)很難進行調試。 –

+0

我刪除了我的答案,它沒用。也許不支持更新關係。至少Ladislav提到它:* AddOrUpdate不支持以任何方式改變關係,所以你不能在下一次遷移時使用它來添加或刪除關係。*(從這裏http://stackoverflow.com/a/8551511/270591。答案來自EF Migrations預覽階段,但也許它仍然有效。) – Slauma

回答

5

AddOrUpdate將重置你不指定爲空(或零int的情況下)列。

我的理解是,這種行爲(其中的方式是可怕的)並不適用於它識別爲按鍵或自動增量列,但顯然它是在你的情況。

我的建議是做一個檢查,以確保該角色不存在於數據庫中,然後做一個標準的add(),如果它沒有。

我這樣做是爲我所有的種子數據,因爲你永遠不知道什麼時候你以後可能會用於更新您種子數據提供一個接口,而你不想種子()方法來覆蓋在該等情況下更改。另外請記住,如果您選擇使用MigrateDatabaseToLatestVersion數據庫初始值設定項,那麼Seed()將在每次重新啓動應用程序時啓動(dll部署,web.config更新等)。

這是最好的種子()方法防守編碼。

更新:朱莉·勒曼具有良好blog post有關此問題。