Da Sie mit LINQ arbeiten, nehme ich an, dass Sie gegen einen LINQ-zu-SQL-Datenkontext richtig arbeiten? Ich habe keinen freien DataContext herumliegen, um dies zu testen, aber das sollte Ihnen einige Ideen geben.
Ich weiß nicht, ob es gegen den Datenkontext funktioniert, aber die meisten davon sind ziemlich einfach (Verkettung von OR-Operator und Contains-Methodenaufruf), so sollte es kein Problem verursachen, wenn die Abfrage in SQL übersetzt.
Zunächst erstelle ich eine benutzerdefinierte Funktion, die mein Prädikat bauen würde:
Func<string, Func<DataItem, bool>> buildKeywordPredicate =
keyword =>
x => x.Title.Contains(keyword)
|| x.Contents.Contains(keyword);
Dies ist eine Funktion, die einen einzelnen String Schlüsselwort nimmt und dann eine andere Funktion zurück, die eine DataItem nimmt und prüft sie gegen das Schlüsselwort. Wenn Sie "Stack" übergeben, erhalten Sie im Prinzip ein Prädikat: x => x.Title.Contains("Stack") || x.Contents.Contains("Stack")
.
Als nächstes, da es viele mögliche Keywords sind, und Sie müssen mit einer ODER-Verknüpfung an die Kette, ich eine andere Hilfsfunktion Kette 2 Prädikate zusammen mit einem OR
Func<Func<DataItem,bool>, Func<DataItem, bool>, Func<DataItem, bool>> buildOrPredicate =
(pred1, pred2) =>
x => pred1(x) || pred2(x);
Diese Funktion nimmt zwei Prädikate und erstellen verbinde sie mit einer ODER-Operation.
diese zwei Funktionen haben, kann ich dann bauen sie meine, wo Prädikat wie folgt aus:
foreach (var word in keywords) {
filter = filter == null
? buildKeywordPredicate(word)
: buildOrPredicate(filter, buildKeywordPredicate(word));
}
Die erste Zeile in der Schleife prüft grundsätzlich, wenn der Filter null ist. Wenn ja, möchten wir einen einfachen Keyword-Filter für uns erstellen.
Wenn der Filter nicht null ist, müssen wir vorhandene Filter mit einer OR-Operation verketten, also übergeben wir den bestehenden Filter und einen neuen Schlüsselwortfilter an buildOrPredicate, um genau das zu tun.
Und dann können wir jetzt den WHERE-Teil der Abfrage erstellen:
var result = data.Where(filter);
in dem komplizierten Prädikat Passing wir gerade gebaut haben.
Ich weiß nicht, ob dies anders als PredicateBuilder ist, aber da wir die Query-Übersetzung auf die LINQ-to-SQL-Engine verschieben, sollte es keine Probleme geben.
Aber wie gesagt, ich habe es nicht mit einem echten Datenkontext getestet, also wenn es irgendwelche Probleme gibt, können Sie in die Kommentare schreiben.
Hier ist die Konsole-Anwendung, die ich zu Test gebaut: http://pastebin.com/feb8cc1e
hoffe, das hilft!
EDIT: Für eine allgemeinere und wieder verwendbare Version, die die Expression Bäume in LINQ ordnungsgemäß unter Verwendung beinhaltet Besuche Thomas Petricek Blog-Post: http://tomasp.net/articles/dynamic-linq-queries.aspx
Das wird leider nur für Funktionen arbeiten. Um das mit Expression Trees zu machen, müssen Sie einen Trick wie diesen verwenden: http://tomasp.net/articles/dynamic-linq-queries.aspx –
Das ist etwas, das Sie dort gemacht haben! .. Derselbe Trick, aber allgemeiner und mehr Ehrfurcht ... Wie auch immer, ich bin jetzt ein Abonnent deines Blogs :-) – chakrit
Danke, dieser hat funktioniert. http://tomasp.net/articles/dynamic-linq-queries.aspx - Tomas Petricek – Amir