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?
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
.
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.
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
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 .....
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.
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>());