update tutorial mvc migrations framework first existing español enable commands code automatic c# entity-framework ef-code-first entity-framework-4.3 dbmigrator

c# - tutorial - Código primero DbMigrator causa un error al construir desde diferentes máquinas



entity framework code first tutorial español (4)

Tenemos un proyecto bajo SCM. Cuando lo construyo desde mi máquina y lo publico en un servidor remoto a través de msdeploy, todo funciona bien.

Cuando mi colega intenta lo mismo con el mismo proyecto, recién extraído de SCM, en el marco de entidades del servidor remoto 4.3.1 DbMigrator arroja:

La migración automática no se aplicó porque daría lugar a la pérdida de datos.

Al parecer, parece que la persona que hace la publicación inicial en el servidor remoto es el "ganador". Si eliminamos la base de datos en el servidor remoto, mi colleaugue puede publicar y se me bloquea. Mis publicaciones dan como resultado el mismo error anterior.

La configuración de DbMigrator ve así:

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() };

Supongo que esto tiene algo que ver con la nueva tabla __MigrationHistory y la desagradable cadena larga hexagonal almacenada en sus filas.

No quiero tomar la responsabilidad completa de publicar en vivo. ¿Qué puedo buscar?


Cambiamos nuestro código de:

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

a

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);

para que podamos observar qué cambios está intentando DbMigrator en el servidor remoto.

En el caso delineado al inicio de esta pregunta (es decir, un colega realiza la carga que crea la base de datos, y luego yo hago la carga generada desde la misma fuente en una máquina diferente), se generan las siguientes declaraciones 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'')

Como se puede ver, la razón por la que DbMigrator está lanzando es porque está intentando cambiar el nombre de 3 tablas que se usan para unir muchas relaciones múltiples invirtiendo los nombres de las tablas que unen, por ejemplo, GalleryImages a ImageGalleries o UserLightboxes a LightboxUsers .

UNA SOLUCIÓN

Esto parece un error en EF 4.3 donde la nomenclatura de tablas de "asociación" parece ser de un orden indeterminado. Dado que el orden de los nombres para este tipo de tablas parece ser indefinido / indeterminado, abordamos esto desde un ángulo diferente, usando la API fluida para obligar a EF a utilizar nombres consistentes en las construcciones de diferentes máquinas:

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"); }); }

Con esto en su lugar, el error ahora desaparece.


Obtengo el mismo error, así que generé un script y lo ejecuté en Query Analyzer. Resulta ser un problema clave de longitud:

¡Advertencia! La longitud máxima de la clave es de 900 bytes. El índice ''PK_dbo .__ MigrationHistory'' tiene una longitud máxima de 1534 bytes. Para alguna combinación de valores grandes, la operación de inserción / actualización fallará.

Parece que el equipo de EntityFramework lo conoce:

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

No estoy seguro de qué problemas esto causará ...


También he encontrado este problema. Curiosamente, la tabla en cuestión no contiene absolutamente ningún dato, es decir, está vacío, algo que Code First ni siquiera parece verificar cuando informa que si aplica las migraciones, se produciría la pérdida de datos.


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