LINQ-viele-zu-viele-Beziehung, wie schreibt man eine korrekte WHERE-Klausel?
Ich viele-zu-viele-Beziehung für meine Tabellen.
Gibt es eine Abfrage:
var query = from post in context.Posts
from tag in post.Tags where tag.TagId == 10
select post;
Ok, es funktioniert gut. Bekomme ich Beiträge mit dem tag angegebenen id.
Habe ich eine Sammlung von tag-ids. Und ich will posts haben jeden tag in meiner Sammlung.
Ich versuche den folgenden Weg:
var tagIds = new int[]{1, 3, 7, 23, 56};
var query = from post in context.Posts
from tag in post.Tags where tagIds.Contains( tag.TagId )
select post;
Funktioniert es nicht. Die Abfrage gibt alle Beiträge, die mit einem der angegebenen tags.
Möchte ich, um eine Klausel wie diese aber dynamicaly für jede Anzahl von tags in der Sammlung:
post.Tags.Whare(x => x.TagId = 1 && x.TagId = 3 && x.TagId = 7 && ... )
möglich, Duplikat der Wie rufe ich die Elemente, die markiert sind und alle mitgelieferten tags in linq?
InformationsquelleAutor Jean Louis | 2012-05-08
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sollte man nicht jedes Projekt post-tags in der äußeren Abfrage; vielmehr müssen Sie eine innere Abfrage, die führt die überprüfung für die äußeren filter. (In SQL, wir nennen es eine korrelierte Unterabfrage.)
Alternative syntax:
Bearbeiten: Korrektur pro Slauma die Klärung. Die version unten gibt Beiträge, die enthalten, mindestens alle tags in der
tagIds
Sammlung.Alternative syntax:
Bearbeiten2: oben Berichtigt pro Slauma. Auch eine andere alternative, die volle Nutzung der Abfrage-syntax unter:
Ich habe
.Any() == false
zu simulieren, dieNOT EXISTS
- operator in Transact-SQL.Sind Sie sich da sicher? Es sieht für mich so aus, dass er immer alle Beiträge. Edit: Er soeben das post.Tags.Alle sperren, die sollten den trick tun, aber Tejs hatte, die ersten.
Das ist wahr, ich bin einfach davon ausgegangen, dass Sie wusste, sowas hab ich nicht. Auch so, mattytommo ist immer noch falsch ist, wie Ihre ursprüngliche Idee (wenn es funktioniert) würden nicht geführt haben nur die Beiträge mit tags zurückgegeben wird. +1, da Sie Ihre aktualisierte Antwort hat die längere linq ich bevorzugen und die alternativen und ist gut geschrieben.
Naja, man kann nicht wirklich sagen, ob er richtig war oder nicht, da würde es abhängen, ob die hypothetische
Contains(IEnumerable<T>)
war logisch äquivalent zuAny
oder eineAll
. Ich hatte vermutet, es wäre äquivalent zu einerAll
(wie in "enthält die Teilmenge").Ah, mit
Any
sieht es sogar besser! Das Letzte code-snippet sieht seltsam aus. Es ist für mich ein gutes Beispiel, dass die extension-Methode syntax ist einfacher zu Lesen, sobald die Abfragen komplexer werden. Ich würde klar lieber die version mit der "Einrückung " cascade" (aber Gedankenstrich anders) 🙂InformationsquelleAutor Douglas
Dies ist eigentlich ziemlich einfach zu tun:
Aktualisiert dann einfach die
All
Erweiterung.Dies würde die Rendite stellen, wo die alle - tags auftreten, in der tagIds Liste. Zum Beispiel: tagIds = ("C#","Java") und eine post, die hat nur das tag "C#". Ihre Abfrage zurückgeben würde diesem post. Aber er will: "Beiträge mit jeden tag in meine Sammlung". I. e.: Nur die Beiträge, die tagged mit "C#" und "Java". Vielleicht, nicht, das Recht einfach zu tun? 🙂
Es ist das gleiche Niveau der Schwierigkeit (oder "ziemlich Leichtigkeit") – Sie müssen swap die Sammlungen, auf denen die
All
undContains
Anrufe gemacht werden. Ich habe Links Versionen für den Vergleich.InformationsquelleAutor Tejs
Eine weitere option ist die Schnittmenge der beiden Listen, wenn Sie wollen, die Sammlung von tags enthalten NUR den Satz, den Sie angeben, und keine andere:
tags.Intersect(tagIds).Count() == tagIds.Length
?Das sieht gut aus! (mit dem Wechsel in die @Trisped Kommentar)
ja, ich bearbeitet die Antwort
Ich wäre nicht sicher, dass die
ToList()
innerhalb vonlet
arbeiten mit LINQ to Entities. (Ich würde erwarten, dass "nicht übersetzen, speichern, Ausdruck" Ausnahme, auchtags
wäre nicht eineIQueryable
mehr.) Meiner Meinung nach, ohne dieToList()
es war in Ordnung.InformationsquelleAutor scottm
Versuchen Sie es mit
Any
.InformationsquelleAutor Daniel A. White