Guybrush Threepwood Geschrieben 18. Juni 2009 Geschrieben 18. Juni 2009 Ich hab eine Tabelle mit mehreren FKs auf eine andere Tabelle. Also in diesem Fall die Tabelle Kunde mit 3 FKs auf die Tabelle Adresse für 3 verschiedene Adressen die man für einen Kunden erfassen kann. Wenn ich jetzt mit Linq einen Kunden auslesen wird aber nur eine der 3 Adressen mit ausgelesen, die anderen beiden bleiben NULL. Das Problem besteht schon in dem SQL Befehl den Linq dazu generiert da nur ein join auf die Tabelle Adresse stattfinden anstatt 3 joins. Weiß jemand ob und wie ich das im Data Modell konfigurieren kann damit alle 3 Adressen mit gelesen werden? Zitieren
flashpixx Geschrieben 18. Juni 2009 Geschrieben 18. Juni 2009 Anhand der Beschreibung kann ich mir nichts vorstellen, poste bitte einmal (Teil-)ERD, Tabellen+Struktur und SQL-Statements für die Abfrage Phil Zitieren
Guybrush Threepwood Geschrieben 18. Juni 2009 Autor Geschrieben 18. Juni 2009 Wie gesagt es gibt 2 Tabellen Kunde und Adresse Adresse hat das Feld ID (und weitere hierfür nicht relevante) und Kunde hat unter anderem die 3 Felder FKAddress, FKShippingAddress und FKInvoiceAddress welche jeweils ein Fremschlüssel auf die Tabelle Adresse sind. Der SQL Befehl wird automatisch von Linq generiert und hier ist halt nur einer statt 3 joins auf die Tabelle Adresse enthalten. Zitieren
flashpixx Geschrieben 18. Juni 2009 Geschrieben 18. Juni 2009 Wie gesagt es gibt 2 Tabellen Kunde und Adresse Adresse hat das Feld ID (und weitere hierfür nicht relevante) und Kunde hat unter anderem die 3 Felder FKAddress, FKShippingAddress und FKInvoiceAddress welche jeweils ein Fremschlüssel auf die Tabelle Adresse sind. Wie sieht die Beziehung aus Kunde-Adresse muss eine 1:NC Beziehung sein. So wie sich das mir darstellt, scheint mir das Modell falsch zu sein. Ich frage den Kunden ab und führe mit einem Left-Join die Verknüpfung durch: select * from kunde left join adressen on kunden.id=adressen.kundenid where adressen.typ = "shipping" (usw) Wenn Du anhand, so wie das verstehe, der Felder auf der Kundentabelle auf die Adressen verknüpfst, dann würde SQL Select wohl so lauten: SELECT * from kunde join adressen on adressen.shippingkundenid on kunden.id das kann genau nur einen Datensatz liefern, egal ob Du nun da weitere Bedingungen anfügst, es wird immer einer bleiben. Du müsstest hier einen Union bilden über alle 3 Felder: (SELECT * from kunde join adressen on adressen.id= kunden.shippingadressid) union (SELECT * from kunde join adressen on adressen.id= kunden.adressid) union (SELECT * from kunde join adressen on adressen.id= kunden.invoiceadressid) ggf kannst Du den Union mit Hilfe von Alias Namen auch in ein Statement zusammen fassen. Ich würde aber sagen, dass das ein Designfehler wären, denn der Kunde hat >= 0 Adressen, die sich ggf in einem Typ unterscheiden. Der Kunde trägt die Unterscheidung nicht, sondern die Adressem Phil Zitieren
Guybrush Threepwood Geschrieben 18. Juni 2009 Autor Geschrieben 18. Juni 2009 Du kannst dir das wie gesagt auch durch 3 joins in einem Datensatz holen: select * from Customer join Address as Address1 on FKAddress = Address1.ID join Address as ShippingAddress on FKShippingAddress = ShippingAddress.ID join Address as InvoiceAddress on FKInvoiceAddress = InvoiceAddress.ID where Customer.ID = 'DE0E421B-EDD2-46A3-9362-489F8C50D447'[/PHP] Nur leider fehlen die 2 weiteren joins in der generierten Abfrage. Der Vorteil wenn du es so rum machst statt in der Adress Tabelle einen FK auf den Kunden zu haben ist der wenn du dir später das Objekt anschaust. So hast du ein Objekt Kunde mit einem Feld Adresse, einem Feld InvoiceAdresse und einem Feld ShippingAdresse jeweils vom Typ Adresse auf die du direkt zugreifen kannst. Anders hättest du ein Objekt Kunde mit einer List von Adressen die du jedesmal nach der gewünschten Adresse durchsuchen müsstest. Zitieren
flashpixx Geschrieben 18. Juni 2009 Geschrieben 18. Juni 2009 (bearbeitet) Der Vorteil wenn du es so rum machst statt in der Adress Tabelle einen FK auf den Kunden zu haben ist der wenn du dir später das Objekt anschaust. So hast du ein Objekt Kunde mit einem Feld Adresse, einem Feld InvoiceAdresse und einem Feld ShippingAdresse jeweils vom Typ Adresse auf die du direkt zugreifen kannst. Mir ist dieses Konstrukt schon bewusst, aber trotzdem ist es per Definition falsch und in der Umsetzung meiner Ansicht nach völlig sinnlos, denn das NC in der Verknüpfung besagt, dass Du eine Anzahl von Adressen >= 0 besitzt. Deine Struktur erlaubt aber in dieser Form 0 <= N1 <= 3 und 0 <= N2 < infinity. D.h. Du konstruierst ein Gebilde, dass unter einem Umstand X dem N1 und einem Umstand Y dem N2 entspricht, wobei, wenn ich den Umstand Y betrachte das N1 in N2 enthalten ist. Am Beispiel ausgedrückt, mache ich ein JOIN von Kunde zu Adresse enthalte ich alle Adressen, mache ich den JOIN über Deine 3 zusätzlichen Schlüsselfelder erhalte ich genau die 3 Adressen, die aber im ersten genannten Konstrukt schon enthalten sind. Du möchtest eine Art der Adresse unterscheiden, d.h. die Unterscheidung gehört immer noch auf die Adressentity Zum Code selbst: Beachte dass hier auf eine Instanz Adresse 3 mal Zugriffen wird. In vielen DBMS Systemen kann man das mit dem Schlüsselwort AS oder ALIAS umgehen bzw deshalb der UNION Phil Bearbeitet 18. Juni 2009 von flashpixx Zitieren
Guybrush Threepwood Geschrieben 18. Juni 2009 Autor Geschrieben 18. Juni 2009 Zum Code selbst: Beachte dass hier auf eine Instanz Adresse 3 mal Zugriffen wird. In vielen DBMS Systemen kann man das mit dem Schlüsselwort AS oder ALIAS umgehen bzw deshalb der UNION Ja stimmt hab ich oben im Beispiel ja auch gemacht, die Frage ist nur wie man Linq sagt das es das auch so machen soll Zitieren
Guybrush Threepwood Geschrieben 18. Juni 2009 Autor Geschrieben 18. Juni 2009 OK das Problem hat sich gerade eben gelöst. und zwar musst du bei Linq angeben welche verknüften Objekte er alle mitladen soll wenn du ein Objekt laden willst. Zum Beispiel: return m_Model.Customer.Include("Communication").Include("Address").First(x => x.ID == id); Da ein Kollege meinte das man hier die Tabellennamen angibt bin ich davon ausgegangen das das so ausreicht und nichts mit dem Problem zu tun haben könnte. Allerdings sind das nicht die Tabellennamen sondern die Namen der Navigation Properties der Linq Objekte. Das heißt wenn man es stattdessen so macht return m_Model.Customer.Include("Communication").Include("Address").Include("InvoiceAddress").Include("ShippingAddress") funktionierts. Trotzdem danke für deine Bemühungen Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.