In T-SQL könnten Sie eine Abfrage haben wie:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
Wie würden Sie das in einer LINQ to Entities-Abfrage replizieren? Ist es überhaupt möglich?
quelle
In T-SQL könnten Sie eine Abfrage haben wie:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
Wie würden Sie das in einer LINQ to Entities-Abfrage replizieren? Ist es überhaupt möglich?
Sie müssen es in Bezug auf die Art und Weise, wie Sie darüber denken, auf den Kopf stellen. Anstatt "in" zu tun, um die Benutzerrechte des aktuellen Elements in einem vordefinierten Satz anwendbarer Benutzerrechte zu finden, fragen Sie einen vordefinierten Satz von Benutzerrechten, ob er den anwendbaren Wert des aktuellen Elements enthält. Dies ist genau die gleiche Art und Weise, wie Sie ein Element in einer regulären Liste in .NET finden würden.
Es gibt zwei Möglichkeiten, dies mit LINQ zu tun: Die eine verwendet die Abfragesyntax und die andere die Methodensyntax. Im Wesentlichen sind sie gleich und können je nach Ihren Vorlieben austauschbar verwendet werden:
Abfragesyntax:
var selected = from u in users
where new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights)
select u
foreach(user u in selected)
{
//Do your stuff on each selected user;
}
Methodensyntax:
var selected = users.Where(u => new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights));
foreach(user u in selected)
{
//Do stuff on each selected user;
}
Meine persönliche Präferenz in diesem Fall könnte die Methodensyntax sein, da ich anstelle der Zuweisung der Variablen den foreach über einen anonymen Aufruf wie diesen ausführen könnte:
foreach(User u in users.Where(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
Syntaktisch sieht dies komplexer aus, und Sie müssen das Konzept der Lambda-Ausdrücke oder -Delegierten verstehen, um wirklich herauszufinden, was vor sich geht. Wie Sie jedoch sehen können, wird der Code dadurch erheblich komprimiert.
Alles hängt von Ihrem Codierungsstil und Ihren Vorlieben ab - alle drei meiner Beispiele machen dasselbe etwas anders.
Eine alternative Methode verwendet nicht einmal LINQ. Sie können dieselbe Methodensyntax verwenden, indem Sie "where" durch "FindAll" ersetzen und dasselbe Ergebnis erhalten, das auch in .NET 2.0 funktioniert:
foreach(User u in users.FindAll(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
Dies sollte Ihrem Zweck genügen. Es vergleicht zwei Sammlungen und prüft, ob für eine Sammlung die Werte mit denen in der anderen Sammlung übereinstimmen
quelle
Wenn Sie VS2008 / .net 3.5 verwenden, lesen Sie Alex James 'Tipp Nr. 8: http://blogs.msdn.com/alexj/archive/2009/03/26/tip-8-writing-where-in-style -queries-using-linq-to-entity.aspx
Verwenden Sie andernfalls einfach die Methode array.Contains (someEntity.Member).
quelle
Ich werde mich in diesem Zusammenhang für Inner Join entscheiden. Wenn ich enthält verwendet hätte, würde es 6 Mal iterieren, obwohl es nur eine Übereinstimmung gibt.
Nachteile von Enthält
Angenommen, ich habe zwei Listenobjekte.
Mit Contains wird nach jedem Element der Liste 1 in Liste 2 gesucht, was bedeutet, dass die Iteration 49 Mal erfolgt !!!
quelle
Auf diese Weise können Sie die in-Klausel direkt mit LINQ-Erweiterungsmethoden überprüfen
quelle
Ich habe auch versucht, mit einer SQL-IN-ähnlichen Sache zu arbeiten - Abfragen gegen ein Entitätsdatenmodell . Mein Ansatz ist ein String-Builder, um einen großen ODER-Ausdruck zu erstellen. Das ist furchtbar hässlich, aber ich fürchte, es ist der einzige Weg, den wir jetzt gehen können.
Nun gut, das sieht so aus:
Arbeiten mit GUIDs in diesem Zusammenhang : Wie Sie oben sehen können, steht in den Abfragezeichenfolgenfragmenten immer das Wort "GUID" vor der GUID. Wenn Sie dies nicht hinzufügen, wird
ObjectQuery<T>.Where
die folgende Ausnahme ausgelöst:Fand dies in MSDN-Foren, könnte hilfreich sein, daran zu denken.
Matthias
... freuen uns auf die nächste Version von .NET und Entity Framework, wenn alles besser wird. :) :)
quelle
Eine alternative Methode zur BenAlabaster-Antwort
Zunächst können Sie die Abfrage folgendermaßen umschreiben:
Sicherlich ist dies "wortreicher" und ein Schmerz zu schreiben, aber es funktioniert trotzdem.
Wenn wir also eine Dienstprogrammmethode hätten, die es einfach macht, diese Art von LINQ-Ausdrücken zu erstellen, wären wir im Geschäft.
Mit einer vorhandenen Dienstprogrammmethode können Sie Folgendes schreiben:
Dadurch wird ein Ausdruck erstellt, der den gleichen Effekt hat wie:
Aber was noch wichtiger ist, funktioniert tatsächlich gegen .NET 3.5 SP1.
Hier ist die Sanitärfunktion, die dies ermöglicht:
Ich werde nicht versuchen, diese Methode zu erklären, außer zu sagen, dass sie im Wesentlichen einen Prädikatausdruck für alle Werte unter Verwendung des valueSelector (dh p => p.User_Rights) erstellt und diese Prädikate zusammen ODER verknüpft, um einen Ausdruck für das Ganze zu erstellen Prädikat
Quelle: http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx
quelle
Echtes Beispiel:
quelle
Ernsthaft? Ihr Leute habt noch nie benutzt
quelle
Checks = NumValues * NumRows
. Da es sich um eine Berechnung vom Typ M * N handelt, ist auch die Zeit für die Durchführung jeder erforderlichen Prüfung gering, wenn eine der beiden Berechnungen klein ist. Ich habe die Einschränkung hinzugefügt, damit cjm30305 weiß, wie eine Testumgebung eingerichtet wird, in der gezeigt wird, warum seine Lösung schlecht ist.where new[] { 1, 2, 3 }.Contains(x)
weniger Vergleiche möglich sindwhere (x == 1 || x == 2 || x == 3)
?