verwendetes Datenbanksystem: MSSQL 2008 R2, Entity Framework 4, Silverlight, .NET 4.0, VS 2010
Guten Tag zusammen
Wie ihr in der Zeichnung am Anhang sehen könnt, habe ich eine Person mit 0...n Adressen.
Die Adressen werden historisiert, mit ValidFrom und ValidTo.
Nun möchte ich, mit LINQ eine Abfrage erstellen, die mir alle gewünschten Personen mit der aktuellen Adresse zurück gibt.
var vQuery = person FROM PersonSet WHERE person.Adresse.ValidTo >= DateTime.Now || person.Adresse.idAdresse == null SELECT person
Diese Abfrage gibt mir alle Personen zurück die eine gültige Adresse haben... Bei den Adressen werden nun aber alle geladen... Wie ihr in der Zeichnung sehen könnt möchte ich aber nur die aktuelle laden...
Beispiel: Wenn eine Person schon an 1'000'000 Adressen gewohnt hat bekomme ich 999'999 Datensätze die ich nicht brauche...
Gibt es da einen guten Ansatz?
Vielen Dank für Hilfe!
Grüsse MiK
Hi,
Deine Anfrage sieht ungewöhnlich aus. Kompiliert das üebrhaupt oder hast Du es nur zur Verdeutlichung geschrieben?
Du kannst Dir im SQL Profiler mal anschauen welches SQL generiert wird und daraus versuchen Rückschlüsse zu ziehen.
Hallo,
wie witte bereits sagte kompiliert deine Anweisung nicht
From person in PersonSet[....]
Bei den Adressen werden nun aber alle geladen
Normalerweise nicht, denn deine LINQ-Query wird in SQL umgewandelt und somit führt die Query der Datenbankserver aus. Zurückgegeben und somit geladen werde nur jene Personen die auf die WHERE ansprechen.
Notfalls guck dir den generierten SQL-String an, damit du deine Zweifel beiseitelegen kannst.
Gruß
Michael
Ich würde dann ja eher so etwas hier versuchen:
Adressen.Where(a => a.ValidFrom ≤ DateTime.Now && a.ValidTo ≥ DateTime.Now).Select(a => a.Personen)
Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)
Hallo zusammen
Das mit dem Query... hihi... war wohl etwas neben den Schuhen 😉
var vQuery = from person in oMichiTestDbEntities.PersonSet
join adress in oMichiTestDbEntities.AdresseSet on person.PersonID equals adress.adrPerson_FK
where adress.adrPostleitzahl == "9300"
select person;
Anstatt auf das ValidTo-Feld nehme ich jetzt eine Postleitzahl... das ist einfacher.
Gemäss meinem Profiler generiert das EF4 folgenden SQL:
SELECT [Extent1].[PersonID] AS [PersonID],
[Extent1].[perVorname] AS [perVorname],
[Extent1].[perNachname] AS [perNachname],
[Extent1].[perGeschlecht] AS [perGeschlecht],
[Extent1].[perGebDatum] AS [perGebDatum],
[Extent1].[perAHVNummer] AS [perAHVNummer]
FROM [dbo].[Person] AS [Extent1]
INNER JOIN [dbo].[Adresse] AS [Extent2]
ON [Extent1].[PersonID] = [Extent2].[adrPerson_FK]
WHERE N'9300' = [Extent2].[adrPostleitzahl]
Wie bekomme ich einen Left Join hin... So sollte der SQL aussehen...
SELECT [Extent1].[PersonID] AS [PersonID],
[Extent1].[perVorname] AS [perVorname],
[Extent1].[perNachname] AS [perNachname],
[Extent1].[perGeschlecht] AS [perGeschlecht],
[Extent1].[perGebDatum] AS [perGebDatum],
[Extent1].[perAHVNummer] AS [perAHVNummer]
FROM [dbo].[Person] AS [Extent1]
LEFT JOIN [dbo].[Adresse] AS [Extent2]
ON [Extent1].[PersonID] = [Extent2].[adrPerson_FK]
WHERE N'9300' = [Extent2].[adrPostleitzahl] OR [Extent2].[AdresseID] is null
Ich habe dieverse Anweisungen mit
.DefaultIfEmpty()
versucht...
Hat jemand eine Idee
Eine Notlösung wäre mit UNION die Personen anzufügen welche noch keine Adresse besitzen.
Der Filter im Originalpost funktioniert vmtl nicht weil du in untergeordneten EntityCollectionen nicht filtern kannst. Also du kannst alle Personen mit ANY finden die schonmal in Berlin gewohnt haben oder wohnen du kannst aber nicht nach diesen Adressen filtern. (Also nur die Berliner Adressen in den Client laden in diesem Beispiel). Deshalb ist Grumbler85's Vorschlag interessant ich weiß aber nicht ob in seinem Beispiel das Relationship Span funktioniert also ob die Adresse dann noch dran ist. Außerdem fehlen die Personen welche keine Adressangaben besitzen, also das Union mal testen.