wake-up-neo.com

Code first DbMigrator verursacht Fehler beim Erstellen von verschiedenen Computern

Wir haben ein Projekt unter SCM. Wenn ich es von meinem Computer aus erstelle und über msdeploy auf einem Remote-Server veröffentliche, funktioniert alles einwandfrei.

Wenn mein Kollege dasselbe mit demselben Projekt versucht, das frisch aus SCM gezogen wurde, wird auf dem Remote-Server-Entitäts-Framework 4.3.1 DbMigrator Folgendes ausgelöst:

Die automatische Migration wurde nicht angewendet, da dies zu Datenverlust führen würde.

Wie sich herausstellt, scheint die Person, die die Erstveröffentlichung auf dem Remote-Server vornimmt, der "Gewinner" zu sein. Wenn wir die Datenbank auf dem Remote-Server ablegen, kann mein Kollege veröffentlichen und ich werde gesperrt. Meine Veröffentlichungen führen zu demselben Fehler wie oben.

Die Konfiguration für DbMigrator sieht ungefähr so ​​aus:

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

Ich nehme an, das hat etwas mit der neuen Tabelle __MigrationHistory und der fiesen langen Hex-Zeichenkette zu tun, die in ihren Zeilen gespeichert ist.

Ich möchte nicht die volle Verantwortung dafür übernehmen, dass das Publizieren gelebt wird. Worauf kann ich achten?

43
spender

Wir haben unseren Code geändert von:

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

zu

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

damit wir beobachten können, welche Änderungen DbMigrator auf dem Remote-Server versucht.

In dem zu Beginn dieser Frage beschriebenen Fall (d. H. Ein Kollege führt einen Upload durch, der eine Datenbank erstellt, gefolgt von einem Upload, der von derselben Quelle auf einem anderen Computer generiert wurde), werden die folgenden SQL-Anweisungen generiert:

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

Wie zu sehen ist, wird DbMigrator ausgelöst, weil versucht wird, 3 Tabellen umzubenennen, die zum Verknüpfen vieler Beziehungen verwendet werden, indem die Namen der zu überbrückenden Tabellen invertiert werden, z. B. GalleryImages in ImageGalleries oder UserLightboxes in LightboxUsers.

Eine Abhilfe

Dies sieht aus wie ein Bug in EF 4.3, wo die Benennung von "Assoziations" -Tabellen in einer unbestimmten Reihenfolge zu sein scheint. Da die Reihenfolge der Namen für diese Art von Tabellen undefiniert/unbestimmt zu sein scheint, haben wir dies aus einem anderen Blickwinkel angegangen und die fließende API verwendet, um EF zu zwingen, die konsistente Benennung für Builds von verschiedenen Computern zu verwenden:

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

Damit ist der Fehler behoben.

8
spender
 public Configuration()
        {
            AutomaticMigrationsEnabled = true;
            AutomaticMigrationDataLossAllowed = true;
        } 
2
msoliman

Ich erhalte den gleichen Fehler, also habe ich ein Skript generiert und es in Query Analyzer ausgeführt. Es stellt sich als Problem mit der Schlüssellänge heraus:

Warnung! Die maximale Schlüssellänge beträgt 900 Byte. Der Index 'PK_dbo .__ MigrationHistory' hat eine maximale Länge von 1534 Bytes. Bei einer Kombination großer Werte schlägt der Einfüge-/Aktualisierungsvorgang fehl.

Das EntityFramework-Team scheint sich dessen bewusst zu sein:

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

Nicht sicher, welche Probleme dies verursachen wird .....

1
Dave

Ich bin auch auf dieses Problem gestoßen. Seltsamerweise enthält die fragliche Tabelle absolut keine Daten, d. H. Sie ist leer. Code First scheint nicht einmal zu prüfen, ob bei Anwendung der Migrationen Datenverluste auftreten würden.

0
user1738579

Ich hatte gerade einen wirklich seltsamen Fehler, der diesem für Entity Framework 6.2.0 ähnlich ist.

Konfiguration.cs:

public class Configuration : DbMigrationsConfiguration<ApplicationDbContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        AutomaticMigrationDataLossAllowed = false;
    }
...
}

Der folgende Code verursachte eine StackOverflowException auf einem Computer, funktionierte aber auf einem anderen einwandfrei.

var migrator = new DbMigrator(new Configuration());
if (migrator.GetPendingMigrations().Any())
{
    migrator.Update();
}

Gelöst durch ein Upgrade wie folgt:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());
0
Ogglas