从不同的机器构build代码第一个DbMigrator会导致错误

我们在SCM下有一个项目。 当我从我的机器构build它,并通过msdeploy发布到远程服务器,一切工作正常。

当我的同事用同一个项目尝试同样的事情时,刚刚从SCM中拉出来,在远程服务器entity framework上4.3.1 DbMigrator抛出:

自动迁移未应用,因为这会导致数据丢失。

事实certificate,初始发布到远程服务器的人似乎是“胜利者”。 如果我们把数据库放在远程服务器上,那么我的同事就可以发布,并且被locking。 我的出版物导致上述相同的错误。

DbMigrator的configuration如下所示:

  var dbMgConfig = new DbMigrationsConfiguration() { AutomaticMigrationsEnabled = true, //***DO NOT REMOVE THIS LINE, //DATA WILL BE LOST ON A BREAKING SCHEMA CHANGE, //TALK TO OTHER PARTIES INVOLVED IF THIS LINE IS CAUSING PROBLEMS AutomaticMigrationDataLossAllowed=false, //***DO NOT REMOVE THIS LINE, ContextType = typeof(TPSContext), MigrationsNamespace = "TPS.Migrations", MigrationsAssembly = Assembly.GetExecutingAssembly() }; 

我认为这与新表__MigrationHistory和存储在其行中的令人讨厌的长hexstring有关。

我不想承担出版活动的全部责任。 我可以注意什么?

我们改变了我们的代码:

  dbMgConfig.AutomaticMigrationDataLossAllowed = false; var mg = new DbMigrator(dbMgConfig); mg.Update(null); 

  dbMgConfig.AutomaticMigrationDataLossAllowed = true; var mg = new DbMigrator(dbMgConfig); var scriptor = new MigratorScriptingDecorator(mg); string script = scriptor.ScriptUpdate(sourceMigration: null, targetMigration: null); throw new Exception(script); 

以便我们可以观察DbMigrator在远程服务器上正在尝试的更改。

在这个问题开始的概述(即同事做上传创build数据库,然后我在不同的机器上从相同的源生成上传),下面的SQL语句生成:

 ALTER TABLE [GalleryImages] DROP CONSTRAINT [FK_GalleryImages_Galleries_Gallery_Id] ALTER TABLE [GalleryImages] DROP CONSTRAINT [FK_GalleryImages_Images_Image_Id] ALTER TABLE [UserLightboxes] DROP CONSTRAINT [FK_UserLightboxes_Users_User_Id] ALTER TABLE [UserLightboxes] DROP CONSTRAINT [FK_UserLightboxes_Lightboxes_Lightbox_Id] ALTER TABLE [ImageLightboxes] DROP CONSTRAINT [FK_ImageLightboxes_Images_Image_Id] ALTER TABLE [ImageLightboxes] DROP CONSTRAINT [FK_ImageLightboxes_Lightboxes_Lightbox_Id] DROP INDEX [IX_Gallery_Id] ON [GalleryImages] DROP INDEX [IX_Image_Id] ON [GalleryImages] DROP INDEX [IX_User_Id] ON [UserLightboxes] DROP INDEX [IX_Lightbox_Id] ON [UserLightboxes] DROP INDEX [IX_Image_Id] ON [ImageLightboxes] DROP INDEX [IX_Lightbox_Id] ON [ImageLightboxes] CREATE TABLE [ImageGalleries] ( [Image_Id] [int] NOT NULL, [Gallery_Id] [int] NOT NULL, CONSTRAINT [PK_ImageGalleries] PRIMARY KEY ([Image_Id], [Gallery_Id]) ) CREATE TABLE [LightboxImages] ( [Lightbox_Id] [int] NOT NULL, [Image_Id] [int] NOT NULL, CONSTRAINT [PK_LightboxImages] PRIMARY KEY ([Lightbox_Id], [Image_Id]) ) CREATE TABLE [LightboxUsers] ( [Lightbox_Id] [int] NOT NULL, [User_Id] [int] NOT NULL, CONSTRAINT [PK_LightboxUsers] PRIMARY KEY ([Lightbox_Id], [User_Id]) ) CREATE INDEX [IX_Image_Id] ON [ImageGalleries]([Image_Id]) CREATE INDEX [IX_Gallery_Id] ON [ImageGalleries]([Gallery_Id]) CREATE INDEX [IX_Lightbox_Id] ON [LightboxImages]([Lightbox_Id]) CREATE INDEX [IX_Image_Id] ON [LightboxImages]([Image_Id]) CREATE INDEX [IX_Lightbox_Id] ON [LightboxUsers]([Lightbox_Id]) CREATE INDEX [IX_User_Id] ON [LightboxUsers]([User_Id]) DROP TABLE [GalleryImages] DROP TABLE [UserLightboxes] DROP TABLE [ImageLightboxes] ALTER TABLE [ImageGalleries] ADD CONSTRAINT [FK_ImageGalleries_Images_Image_Id] FOREIGN KEY ([Image_Id]) REFERENCES [Images] ([Id]) ON DELETE CASCADE ALTER TABLE [ImageGalleries] ADD CONSTRAINT [FK_ImageGalleries_Galleries_Gallery_Id] FOREIGN KEY ([Gallery_Id]) REFERENCES [Galleries] ([Id]) ON DELETE CASCADE ALTER TABLE [LightboxImages] ADD CONSTRAINT [FK_LightboxImages_Lightboxes_Lightbox_Id] FOREIGN KEY ([Lightbox_Id]) REFERENCES [Lightboxes] ([Id]) ON DELETE CASCADE ALTER TABLE [LightboxImages] ADD CONSTRAINT [FK_LightboxImages_Images_Image_Id] FOREIGN KEY ([Image_Id]) REFERENCES [Images] ([Id]) ON DELETE CASCADE ALTER TABLE [LightboxUsers] ADD CONSTRAINT [FK_LightboxUsers_Lightboxes_Lightbox_Id] FOREIGN KEY ([Lightbox_Id]) REFERENCES [Lightboxes] ([Id]) ON DELETE CASCADE ALTER TABLE [LightboxUsers] ADD CONSTRAINT [FK_LightboxUsers_Users_User_Id] FOREIGN KEY ([User_Id]) REFERENCES [Users] ([Id]) ON DELETE CASCADE CREATE TABLE [__MigrationHistory] ( [MigrationId] [nvarchar](255) NOT NULL, [CreatedOn] [datetime] NOT NULL, [Model] [varbinary](max) NOT NULL, [ProductVersion] [nvarchar](32) NOT NULL, CONSTRAINT [PK___MigrationHistory] PRIMARY KEY ([MigrationId]) ) BEGIN TRY EXEC sp_MS_marksystemobject '__MigrationHistory' END TRY BEGIN CATCH END CATCH INSERT INTO [__MigrationHistory] ([MigrationId], [CreatedOn], [Model], [ProductVersion]) VALUES ('201203030113082_AutomaticMigration', '2012-03-03T01:13:08.986Z', 0x[removedToShortenPost], '4.3.1') 

可以看出, DbMigrator抛出的原因是因为它试图重命名3个表,通过反转连接表的名字,例如GalleryImagesImageGalleriesUserLightboxesLightboxUsers来重新连接许多关系。

解决方法

这看起来像EF 4.3中的一个错误 ,其中“关联”表的命名似乎是不确定的顺序。 鉴于这些表的名称的sorting似乎是不确定的/不确定的,我们从不同的angular度来处理这个问题,使用stream利的API来强制EF使用来自不同机器的跨生成的一致命名:

  protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder .Entity<Gallery>() .HasMany(p => p.Images) .WithMany(p => p.Galleries) .Map(c => { c.MapLeftKey("Gallery_Id"); c.MapRightKey("Image_Id"); c.ToTable("GalleryImages"); }); modelBuilder .Entity<User>() .HasMany(p => p.Lightboxes) .WithMany(p => p.Users) .Map(c => { c.MapLeftKey("User_Id"); c.MapRightKey("Lightbox_Id"); c.ToTable("UserLightboxes"); }); modelBuilder .Entity<Image>() .HasMany(p => p.Lightboxes) .WithMany(p => p.Images) .Map(c => { c.MapLeftKey("Image_Id"); c.MapRightKey("Lightbox_Id"); c.ToTable("ImageLightboxes"); }); } 

有了这个,错误现在消失了。

  public Configuration() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = true; } 

我得到相同的错误,所以我生成了一个脚本,并在查询分析器中运行它。 原来是一个关键的长度问题:

警告! 最大密钥长度是900字节。 索引“PK_dbo .__ MigrationHistory”的最大长度为1534字节。 对于某些较大值的组合,插入/更新操作将失败。

看起来EntityFramework团队知道这一点:

http://entityframework.codeplex.com/workitem/1216

不知道这会造成什么问题…..

我也遇到过这个问题。 奇怪的是,所讨论的表格绝对不包含任何数据,即它是空的,Code First甚至在报告如果应用迁移时似乎不检查数据,就会发生数据丢失。