Bitte helfen Sie einem EF n00b beim Entwurf seiner Datenbank. Ich habe mehrere Unternehmen, die mehrere Produkte herstellen, daher gibt es eine Viele-zu-Viele-Beziehung zwischen Unternehmen und Produkten. Ich habe eine Zwischentabelle, Company_Product, die sie in Beziehung setzt.
Jede Firma / Produktkombination hat eine eindeutige Artikelnummer. Zum Beispiel haben Acme-Widgets die SKU 123, aber Omega-Widgets haben die SKU 456. Ich habe die SKU als Feld in die Company_Product-Zwischentabelle aufgenommen.
EF hat ein Modell mit einer 1: * - Beziehung zwischen den Tabellen Company und Company_Product und einer 1: * - Beziehung zwischen den Tabellen Product und Company_Product generiert. Ich möchte wirklich eine : Beziehung zwischen Unternehmen und Produkt. Vor allem aber gibt es keine Möglichkeit, direkt vom Modell auf die SKU zuzugreifen.
Muss ich die SKU in eine eigene Tabelle schreiben und einen Join schreiben, oder gibt es einen besseren Weg?
Ich habe das gerade in einem neuen VS2010-Projekt (EFv4) getestet, und hier ist, was ich gefunden habe:
Wenn Ihre assoziative Tabelle in der Mitte (Company_Product) NUR die 2 Fremdschlüssel zu den anderen Tabellen (CompanyID und ProductID) enthält, endet die Modellierung der Viele-zu-viele-Beziehung dann, wenn Sie dem Designer alle 3 Tabellen hinzufügen. Es generiert nicht einmal eine Klasse für die Company_Product-Tabelle. Jedes Unternehmen hat eine Produktsammlung und jedes Produkt hat eine Firmensammlung.
Wenn Ihre assoziative Tabelle (Company_Product) jedoch andere Felder hat (z. B. SKU, ihren eigenen Primärschlüssel oder andere beschreibende Felder wie Daten, Beschreibungen usw.), erstellt der EF-Modellierer eine separate Klasse was du schon gesehen hast.
Die Klasse in der Mitte mit 1: * Beziehungen zu Unternehmen und Produkt zu haben, ist keine schlechte Sache, und Sie können immer noch die gewünschten Daten mit einigen einfachen Abfragen erhalten.
%Vor%Es ist zwar nicht so einfach, die Beziehungen des Modells zu steuern, wenn Sie beispielsweise bereits Entitätsobjekte geladen haben, aber dafür ist eine Datenschicht zuständig. Verkapseln Sie die Abfragen, die die gewünschten Daten erhalten. Wenn Sie diese mittlere Company_Product-Klasse wirklich loswerden möchten und die Viele-zu-Viele direkt im Klassenmodell darstellen möchten, müssen Sie die Company_Product-Tabelle entfernen, um nur die 2 Fremdschlüssel zu enthalten, und loswerden der SKU.
Eigentlich sollte ich nicht sagen, dass du das tun musst ... du könntest vielleicht einige Änderungen am Designer vornehmen und es auf diese Weise einrichten. Ich werde es versuchen und berichten.
AKTUALISIEREN
Wenn ich die SKU in der Company_Product-Tabelle behalte (dh mein EF-Modell hatte 3 Klassen, nicht 2; es hat die Klasse Company_Payload mit einem 1: * zu den anderen 2 Tabellen erstellt), habe ich versucht, eine Verknüpfung direkt zwischen Firma und Produkt. Die Schritte, denen ich folgte, waren:
Aber es funktioniert nicht. Es gibt diesen Fehler: Fehler 3025: Problem beim Zuordnen von Fragmenten ab Zeile 175: Muss die Zuordnung für alle Schlüsseleigenschaften (Company_Product.SKU) der Tabelle Company_Product angeben.
Diese bestimmte Verknüpfung ist daher ungültig, weil sie Company_Product als Tabelle verwendet, aber das SKU-Feld keinem Objekt zuordnet.
Auch während ich das recherchierte, stieß ich auf diesen "Best Practice" Leckerbissen aus dem Buch Entity Framework 4.0 Recipes (beachten Sie, dass sie für eine Assoziationstabelle mit zusätzlichen Feldern neben zwei FKs die zusätzlichen Felder als bezeichnen die "Nutzlast". In Ihrem Fall ist SKU die Nutzlast in Company_Product.
Best Practice
Leider ein Projekt das beginnt mit mehreren, Nutzlast-frei, viele-zu-viele Beziehungen enden oft mit mehrere, Nutzlast-reiche, viele-zu-viele Beziehungen. Refactoring eines Modells, besonders spät in der Entwicklung Zyklus, um Nutzlasten in der Viele-zu-viele-Beziehungen können sein langweilig. Nicht nur sind zusätzliche Entitäten eingeführt, aber die Abfragen und Navigationsmuster durch die Beziehungen ändern sich auch. Etwas Entwickler argumentieren, dass jeder Viele-zu-viele-Beziehung sollte beginnen mit etwas Payload, typischerweise a synthetischer Schlüssel, also das Unvermeidliche Hinzufügung von mehr Nutzlast hat deutlich weniger Auswirkungen auf die Projekt.
Hier ist also die beste Vorgehensweise. Wenn Sie eine Nutzlast haben, Viele-zu-viele-Beziehung und du denke, dass es eine Chance gibt, dass es könnte im Laufe der Zeit ändern, um eine Nutzlast aufzunehmen, Beginnen Sie mit einer zusätzlichen Identitätsspalte in die Verbindungstabelle. Beim Importieren der Tabellen in Ihr Modell, werden Sie bekommen zwei Eins-zu-viele-Beziehungen, die bedeutet der Code, den Sie schreiben und das Modell Sie werden für jede Nummer bereit sein von zusätzlichen Nutzlastspalten, die Kommen Sie mit, wenn das Projekt reift. Das Kosten einer zusätzlichen Ganzzahlidentität Spalte ist normalerweise ein ziemlich kleiner Preis zu zahlen, um das Modell mehr zu halten flexibel.
(Aus Kapitel 2. Grundlagen der Modellierung von Entitätsdaten, 2.4. Modellierung einer Viele-zu-Viele-Beziehung mit einer Payload)
Klingt wie ein guter Rat. Zumal Sie bereits eine Payload (SKU) haben.
Ich möchte nur das Folgende zu Samuels Antwort hinzufügen:
Wenn Sie direkt von einer Seite einer Viele-zu-Viele-Beziehung (mit Payload) zu der anderen abfragen möchten, können Sie den folgenden Code verwenden (unter Verwendung des gleichen Beispiels):
%Vor% Die Variable products
würde dann alle Product
Datensätze sein, die dem Company c
Datensatz zugeordnet sind. Wenn Sie die Artikelnummer für jedes Produkt hinzufügen möchten, können Sie eine anonyme Klasse wie folgt verwenden:
Sie können die erste Abfrage in einer schreibgeschützten Eigenschaft der Einfachheit halber wie folgt kapseln:
%Vor% Sie können das nicht mit der Abfrage ausführen, die die SKU enthält, da Sie keine anonymen Typen zurückgeben können. Sie müssten eine bestimmte Klasse haben, die in der Regel entweder durch Hinzufügen einer nicht zugeordneten Eigenschaft zur Klasse Product
oder durch Erstellen einer anderen Klasse, die von Product
erbt, die eine SKU-Eigenschaft hinzufügen würde. Wenn Sie jedoch eine geerbte Klasse verwenden, können Sie keine Änderungen daran vornehmen und lassen Sie sie von EF verwalten - das wäre nur für die Anzeige nützlich.
Prost. :)
Tags und Links entity-framework many-to-many