Ich erstelle eine Methode, die ein oder mehrere Kriterien für die Abfrage einer Datenbank mit LINQ verwendet. Ich habe dies:Dynamisches ODER in LINQ ohne den PredicateBuilder
public ICollection<MyClass> FindAllBy(params Expression<Func<MyClass, bool>>[] criteria)
{
using (var ctx = new MyContext())
{
IQueryable<MyClass> result = ctx.MyClasses.AsNoTracking();
if (criteria != null && criteria.Length > 0)
{
foreach (var item in criteria)
{
result = result.Where(item);
}
}
return result.ToList();
}
}
Dies hat den Effekt, dass, wenn ich für ein Objekt suche mit Id 1 und einem mit Id 2 ich nichts bekommen, da keine Zeile hat sowohl eine Id von 1 und 2. So muß ich eine OR-Klausel. Ich fand diese Seite:
http://www.albahari.com/nutshell/predicatebuilder.aspx
, die eine PredicateBuilder Klasse hat, die ich dies machen folgende Zwecke verwendet:
public ICollection<PhotoFile> FindAllBy(params Expression<Func<PhotoFile, bool>>[] criteria)
{
using (var ctx = new CotanContext())
{
var predicate = PredicateBuilder.False<PhotoFile>();
if (criteria != null && criteria.Length > 0)
{
foreach (var item in criteria)
{
predicate = predicate.Or(item);
}
}
return ctx.PhotoFiles.Where(predicate).ToList();
}
}
Mein Code unterscheidet sich geringfügig von der Seite, dass ich in einem Ausdruck gelangen in die Methode, die ich dann in die Predicate.Or-Methode übergeben.
Die obige Methode gibt einen The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
Fehler. Das macht Sinn, da Entity Framework nicht weiß, wie man diesen Code in eine gültige Abfrage übersetzt.
Die Lösung auf der verlinkten Seite ist das Herunterladen ihres Nuget-Pakets oder Quellcodes, wodurch dieser Code funktioniert. Allerdings fühle ich mich nicht wohl dabei, mehrere Hundert Zeilen von unbekanntem und scheinbar unerprobtem Code für eine einzelne Funktion einzubauen, die meiner Meinung nach vor einiger Zeit von Microsoft in LINQ eingebaut sein sollte. Auch der Hauptentwickler meines Projekts hat in der Vergangenheit dringend davon abgeraten, unbekannte Pakete zu verwenden, die nicht direkt von Microsoft stammen. Ich arbeite mit sensiblen Informationen, also wäre ich lieber sicher als Nachsicht.
Also meine Frage: Gibt es eine Möglichkeit, eine OR-Funktion in LINQ zu erhalten, ohne ein externes Nuget-Paket verwenden zu müssen?
Müssen Sie wirklich die Klauseln in Ihre Funktion übergeben? Warum nicht ein IQueryable <> zurückgeben und dem Anrufer überlassen, was zu tun ist? – Neil
In der ersten Methode zumindest mache ich das. Ich mache das IQueryable nur zu einem IEnumerable, wenn ich ToList() aufruft. Ich verwende die Where() - Überladung, die Ausdrücke akzeptiert und ein anderes IQueryable zurückgibt. Und die Or-Methode im zweiten Beispiel gibt nur einen anderen Ausdruck zurück, sodass auch dort keine Datenbank aufgerufen wird. – ohyeah
Verwenden Sie [dieses Prädikat Builder] (https://patemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/) statt –