Zum Inhalt springen

Linq to Entities: Mehrere FKs auf die selbe Tabelle


Guybrush Threepwood

Empfohlene Beiträge

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?

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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 von flashpixx
Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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 :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...