Wir haben eine Datenbank, in der eine Tabelle Datensätze enthält, die unter mehrere andere Tabellen untergeordnet werden können. Es hat einen "weichen" Fremdschlüssel, der aus der ID des Besitzers und einem Tabellennamen besteht. Dieses (Anti-) Muster wird als "polymorphe Assoziationen" bezeichnet. Wir wissen, dass es nicht das beste Datenbankdesign aller Zeiten ist, und wir werden es zu gegebener Zeit ändern, aber nicht in naher Zukunft. Lassen Sie mich ein vereinfachtes Beispiel zeigen:Modeling polymorphe Assoziationsdatenbank zuerst vs Code-first
Beide Event
, Person
und Product
Aufzeichnungen in Comment haben. Wie Sie sehen, gibt es keine harten FK-Einschränkungen.
In Entity Framework ist es möglich, dieses Modell zu unterstützen, indem sie Comment
in EventComment
usw. sublassing und lassen Event
eine EventComments
Sammlung, etc .:
Die Unterklassen und die Verbände werden manuell hinzugefügt, nachdem Erzeugen des Basismodells aus der Datenbank. OwnerCode
ist der Diskriminator in diesem TPH Modell. Bitte beachten Sie, dass Event
, Person
und Product
völlig unterschiedliche Entitäten sind. Es macht keinen Sinn, eine gemeinsame Basisklasse für sie zu haben.
Dies ist Datenbank-zuerst. Unser Real-Life-Modell funktioniert so, kein Problem.
OK. Jetzt wollen wir uns zuerst mit dem Code befassen. Also begann ich mit dem Reverse-Engineering der Datenbank in ein Code-First-Modell (EF Power Tools) und fuhr fort, die Unterklassen zu erstellen und die Assoziationen und die Vererbung zuzuordnen. Versucht, eine Verbindung mit dem Modell in Linqpad herzustellen. Dann begann der Ärger.
Wenn eine Abfrage mit diesem Modell auszuführen versucht, wirft es eine InvalidOperationExeception
Die Fremdschlüsselkomponente ‚ownerID‘ ist keine deklarierte Eigenschaft auf Typ ‚EventComment‘. Stellen Sie sicher, dass es nicht explizit aus dem Modell ausgeschlossen wurde und dass es sich um eine gültige primitive Eigenschaft handelt. Diese
passiert, wenn ich bidirektionale Assoziationen haben und OwnerId
wird als Eigenschaft in Comment
abgebildet. Die Abbildung in meinem EventMap
Klasse (EntityTypeConfiguration<Event>
) sieht wie folgt aus:
this.HasMany(x => x.Comments).WithRequired(c => c.Event)
.HasForeignKey(c => c.OwnerId);
So habe ich versucht, den Verein ohne OwnerId
im Modell abzubilden:
this.HasMany(x => x.Comments).WithRequired().Map(m => m.MapKey("OwnerId"));
Dies wirft ein MetaDataException
Das angegebene Schema ist nicht gültig. Fehler: (10,6): Fehler 0019: Jeder Eigenschaftsname in einem Typ muss eindeutig sein. Der Eigenschaftsname 'OwnerId' wurde bereits definiert. (11,6): Fehler 0019: Jeder Eigenschaftsname in einem Typ muss eindeutig sein. Der Eigenschaftsname 'OwnerId' wurde bereits definiert.
Wenn ich entferne zwei der drei einheits Kommentar Verbände es in Ordnung ist, aber das ist natürlich nicht eine Heilung.
Einige weitere Details:
- Es ist möglich, eine Arbeits DbContext Modell ("Code zweite") von der edmx zu erstellen, indem Sie einen DbContext Generator Element hinzugefügt wird. (Dies wäre vorerst eine Ausrede).
- Wenn ich das funktionierende Code-First-Modell (mit einer Assoziation) nach edmx (
EdmxWriter
) exportiert, scheint die Assoziation im Speichermodell zu sein, während sie im ursprünglichen edmx Teil des konzeptionellen Modells sind.
Also, wie kann ich diesen Modellcode zuerst erstellen? Ich denke, der Schlüssel ist, wie man Code anweist, zuerst die Assoziationen im konzeptionellen Modell, nicht das Speichermodell abzubilden.
Haben Sie das Modell jemals mit Code-First arbeiten lassen? Interessant, dass es für Db-First/EDMX funktioniert. Ich hatte eine Frage zu einem ähnlichen Modell und das letzte Wort von CodePlex war im Grunde "nicht unterstützt" und "grundlegende EF-Beschränkung" (http://stackoverflow.com/a/14880084/270591). Aber wenn Ihr Modell mit EDMX arbeitet, scheint es tatsächlich eine Code-First-Einschränkung zu sein, keine allgemeine EF-Beschränkung. – Slauma
Ja, das Datenbank-erste Modell funktioniert (Gott sei Dank). Das reale Modell ist sogar noch komplexer, weil es Vererbungsdiskriminatoren aufweist. Kein Problem. Code zuerst ist das Problem. Hast du dein Model db-first schon einmal probiert? –
Nein, habe es noch nie versucht. Wir wissen, dass Code-First nicht alle Edmx-Funktionen unterstützt, aber ich habe wirklich keinen Unterschied in dieser Situation erwartet. Ich habe BTW nur um eine Bestätigung in diesem alten Problem auf CodePlex gebeten (https://entityframework.codeplex.com/workitem/865, letzter Kommentar auf der Seite). Nicht sicher, ob ich eine Antwort in einem geschlossenen Gegenstand erwarten kann. – Slauma