2012-12-04 5 views
54

Ich möchte Kaskadenlöschungen für eine Verknüpfungstabelle mit Entity-Framework-Code-zuerst deaktivieren. Wenn beispielsweise viele Benutzer viele Rollen haben und ich versuche, eine Rolle zu löschen, möchte ich, dass das Löschen blockiert wird , es sei denn, sind derzeit keine Benutzer mit dieser Rolle verknüpft. Ich entferne bereits die Kaskade löschen Konvention in meinem OnModelCreating:Wie kaskadierende Löschung für Verknüpfungstabellen in EF-Code-zuerst deaktivieren?

protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
    ... 
    modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 

Und dann stelle ich die Benutzer-Rollen-Link System:

modelBuilder.Entity<User>() 
    .HasMany(usr => usr.Roles) 
    .WithMany(role => role.Users) 
    .Map(m => { 
     m.ToTable("UsersRoles"); 
     m.MapLeftKey("UserId"); 
     m.MapRightKey("RoleId"); 
    }); 

Doch wenn EF die Datenbank erstellt, erstellt es eine Lösch Kaskade für die Fremdschlüsselbeziehungen, z.

ALTER TABLE [dbo].[UsersRoles] WITH CHECK ADD CONSTRAINT [FK_dbo.UsersRoles_dbo.User_UserId] FOREIGN KEY([UserId]) 
REFERENCES [dbo].[User] ([UserId]) 
ON DELETE CASCADE 
GO 

ALTER TABLE [dbo].[UsersRoles] WITH CHECK ADD CONSTRAINT [FK_dbo.UsersRoles_dbo.Role_RoleId] FOREIGN KEY([RoleId]) 
REFERENCES [dbo].[Role] ([RoleId]) 
ON DELETE CASCADE 
GO 

Wie kann ich EF stoppen, diese Löschkaskade zu erzeugen?

Antwort

93

Ich habe die Antwort bekommen. :-) Diese Kaskadenlöschungen wurden wegen ManyToManyCascadeDeleteConvention erstellt. Sie müssen diese Konvention entfernen es Kaskade von der Erstellung zu verhindern löscht für Link-Tabellen:

modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); 
+0

Danke das half mir eine Tonne. Neugierig, hast du BEIDE Konventionen oder nur die Viele-zu-Viele-Konventionen entfernt? – kmehta

+7

Eigentlich habe ich gerade die one-to-many-Konvention entfernt und sie selektiv für ein oder zwei Entitäten wieder aktiviert. Meine Notizen dazu sagen, dass, weil (im Gegensatz zu eins-zu-vielen) Sie die Fluent-API nicht verwenden können, um das Kaskaden-Löschen für eine Viele-zu-Viele wieder zu aktivieren, indem Sie '.WillCascadeOnDelete (true)', * all * Die Viele-zu-Viele-Tabellen müssen entweder kaskadieren oder nicht kaskadieren. Ich überlegte, sie alle Kaskaden als das kleinere Übel zu haben, denn meistens, wenn ich etwas lösche, das mit einer Viele-zu-Viele-Verknüpfungstabelle verlinkt ist, möchte ich, dass die Dinge, mit denen es verknüpft ist, ebenfalls gelöscht werden. – Jez

+1

Das schien nicht zu funktionieren. Mein Problem ist, wenn ich zwei Eigenschaften eines Objekts des gleichen Typs habe (erstellt von diesem Benutzer und zuletzt von diesem Benutzer bearbeitet). Ich hatte gehofft, dass dies den Fehler "kann Zyklus oder mehrere Kaskadenpfade verursachen" entfernen kann, aber es hat nicht funktioniert. Vorschläge? – Rogala

0

Ich glaube, dass ManyToManyCascadeDeleteConvention global ist nicht eine kluge Wahl ausschalten. Stattdessen ist es besser, es auszuschalten nur für die betroffenen Tabelle.

Dies kann durch Bearbeiten der generierten Migrationsdatei für die Eigenschaft cascadeDelete erreicht werden. Zum Beispiel:

AddForeignKey("dbo.UsersRoles", "UserId", "dbo.User", "UserId", cascadeDelete: false);

0

ich mit Ebram Khalil einig, dass es aus einer einzigen Tabelle dreht eine gute Option ist. Ich mag so nah an die automatisch gebaut Migrationen bleiben, wie ich kann, aber so würde ich es in OnModelCreating ein:

modelBuilder.Entity<User>() 
    .HasMany(usr => usr.Roles) 
    .WithMany(role => role.Users) 
    .Map(m => { 
     m.ToTable("UsersRoles"); 
     m.MapLeftKey("UserId"); 
     m.MapRightKey("RoleId"); 
    }) 
    .WillCascadeOnDelete(false); 

Ich glaube, das bewahrt die löschen Sie die andere Richtung, so dass, wenn beide erforderlich sein geblockt (sinnvoll in diesem Beispiel) müsste ein ähnlicher Aufruf erfolgen, beginnend mit Entity<User>(Role)

Natürlich kommt dies erst nach der Beantwortung der Frage. So könnte es 2012 nicht gültig gewesen sein.

Verwandte Themen