2012-11-21 6 views
6

Ich versuche, eine vorhandene Datenbank mit Entity Framework Code First Fluent API zuzuordnen. Ich kämpfe in einer Situation mit einer Viele-zu-Viele-Beziehung und Kaskadenlöschung.So kaskadieren Sie das Löschen nur in der Join-Tabelle mit Entity Framework Code Erste Fluent-API

Hier ist meine zwei POCO Klassen:

public class Foo 
{ 
    public int FooId; 
    public string FooDescription; 
    public IList<Bar> Bars; 
} 
public class Bar 
{ 
    public int BarId; 
    public string BarDescription; 
} 

Vorerst ich nur eine Navigationseigenschaft von Foo zu Bar haben. Das liegt daran, dass es in meinem realen Szenario für niemanden sinnvoll ist, von Bar zu Foo zu gehen. Die Beziehung von Foo zu Bar ist eigentlich 0, was bedeutet, dass eine Instanz von Foo keine Instanzen von Bar erfordert.

Meine vorhandene Datenbank hat eine Join-Tabelle zwischen diesen beiden Tabellen. Diese Tabelle sieht wie folgt aus:

modelBuilder.Entity<Foo>() 
    .HasMany(t => t.Bars) 
    .WithMany() 
    .Map(m => 
    { 
    m.ToTable("Foo_Bar"); 
    m.MapLeftKey("FooId"); 
    m.MapRightKey("BarId"); 
    }); 

Das funktioniert perfekt für Einsätze:

create table Foo_Bar(
FooId int not null, 
BarId int not null 
); 

Weil ich es vorziehen, nicht so ein POCO-Klasse in meinem Projekt zu erstellen, ich die Tabelle wie folgt zugeordnet. Entity einfügen auf Foo und dann auf der vorhandenen Foo_Bar Tabelle.

Aber wenn ich eine Foo löschen, möchte ich die Datensätze in der Join-Tabelle löschen, aber nicht in der untergeordneten Tabelle. Bedeutung Ich möchte Datensätze unter Foo_Bar löschen, diese Kaskade jedoch nicht auf Bar erweitern.

Ist eine solche Zuordnung möglich? Ich sollte erwähnen, dass ich in meinem Kontext sowohl OneToManyCascadeDeleteConvention als auch ManyToManyCascadeDeleteConvention entfernt habe, weil ich 99% der Zeiten nicht Kaskade löschen werde. Dies ist eine spezifische Situation.

Durch Verfolgen der SQL erzeugt durch Entity Framework Ich habe auch bemerkt, dass, wenn ich eine Foo Instanz und stellen Sie alle Bars im Inneren zu EntityState.Deleted abrufen, EF beide Datensätze in Foo_Bar löscht und Bar. Eine letzte Sache, die ich erwähnen sollte, ist, dass ich in einem getrennten Szenario arbeite.

Ich habe versucht, dies zu durchsuchen, aber es scheint, dass ich nicht die richtigen Schlüsselwörter verwende, da ich niemanden in einer solchen Situation finden konnte. An diesem Punkt ist die einzige Lösung, die ich sehe, Map eine FooBar Klasse, aber ich hoffe, es gibt einen Weg, dies zu tun.

--edit

Es scheint, dass mein Ansatz war anfangs falsch zu löschen. Als ich versuchte, löschte ich nicht die Instanz Foo mit seiner Liste von Bar gefüllt. Nach dieser Änderung erstellt Entity Framwork eine Löschanweisung für jede Bar in der Liste. Ich habe immer noch Probleme mit der Aktualisierung wie Hinzufügen und Entfernen von Elementen zur gleichen Zeit. Werde mehr Tests machen und hier posten.

Vielen Dank im Voraus.

Antwort

6

Aber wenn ich ein Foo löschen, möchte ich die Datensätze in der Join-Tabelle löschen, aber nicht auf der untergeordneten Tabelle. Bedeutung Ich möchte Datensätze auf Foo_Bar löschen, diese Kaskade aber nicht auf Bar erweitern.

Ist eine solche Zuordnung möglich?

Dies ist eigentlich die einzige Zuordnung, die möglich ist. Sie können auf die Bar Tabelle Kaskadierung gelöscht werden, da in der Beziehung nicht verlängern (von Datenbank-Schema-Perspektive) die Foo_Bar Join-Tabelle die abhängigen in der Beziehung ist und Bar ist die Haupt. Im Allgemeinen ist das cacscading delete nur wirksam, wenn Sie den Prinzipal löschen, aber nicht, wenn Sie das abhängige löschen.

Sie müssen sich also keine Sorgen machen, dass ein Bar gelöscht werden könnte, wenn Sie einen Foo löschen und Sie keine spezielle Einstellung dafür vornehmen müssen.

Aber Sie haben ein Problem, wenn Sie die ManyToManyCascadeDeleteConvention entfernt haben. Es wirkt global für das gesamte Modell und es gibt keine Option, die kaskadierende Löschung für eine bestimmte Viele-zu-Viele-Beziehung erneut zu aktivieren. (Es gibt keine WillCascadeOnDelete(true) für viele-zu-viele-Beziehung wie es eins für Eins-zu-viele oder eins-zu-eins-Beziehungen gibt.)

Sind Sie sicher, dass das Entfernen der ManyToManyCascadeDeleteConvention wirklich in Ihrem Modell erforderlich ist? Ich habe nie ein Modell gefunden, wo es sinnvoll wäre nicht löschen Sie die zugehörigen Einträge in der Join-Tabelle, wenn eine der verbundenen Entitäten (Foo oder Bar) gelöscht wird.

+0

Ich stimme dir zu. Es ist das einzig mögliche Mapping. Ich kann mich nicht erinnern, warum ich das angegeben habe, als ich es geschrieben habe. Bezüglich der Notwendigkeit, die Konvention zu entfernen, habe ich ein Szenario, bei dem ein Ende der Viele-zu-Viele-Beziehung eine Tabelle mit Datensätzen ist, die mit der Geschäftslogik verknüpft sind. Der Benutzer kann seine Datensätze nicht bearbeiten. Wenn Sie kein Kaskaden-Löschen an diesem Ende erstellen, auch wenn jemand versehentlich versucht, einen Datensatz zu löschen, wird nichts unterbrochen. Aber ich denke, das ist in der Tat eine Ausnahme. Für jetzt werde ich die Konvention aktivieren und die Ausnahmen auf andere Weise behandeln. Vielen Dank. –

Verwandte Themen