(編集:私は間違った質問をしました。私が抱えている本当の問題は、LINQ-to-SQL述語を単一の述語に構成することで終わりました-しかし、これはいくつかの良い答えを得たので、私はそれを残しました!)
次の検索テキストがあるとします。
"keyword1 keyword2 keyword3 ... keywordN"
私は次のSQLで終わりたい:
SELECT [columns] FROM Customer
WHERE
(Customer.Forenames LIKE '%keyword1%' OR Customer.Surname LIKE '%keyword1%')
AND
(Customer.Forenames LIKE '%keyword2%' OR Customer.Surname LIKE '%keyword2%')
AND
(Customer.Forenames LIKE '%keyword3%' OR Customer.Surname LIKE '%keyword3%')
AND
...
AND
(Customer.Forenames LIKE '%keywordN%' OR Customer.Surname LIKE '%keywordN%')
事実上、検索テキストをスペースで分割し、各トークンをトリミングし、各トークンに基づいてマルチパート OR 句を作成し、句を AND 結合します。
私はこれをLinq-to-SQLで行っていますが、サブ述語の任意の長いリストに基づいて述語を動的に作成する方法がわかりません。句の数がわかっている場合、述語を手動で構成するのは簡単です。
dataContext.Customers.Where(
(Customer.Forenames.Contains("keyword1") || Customer.Surname.Contains("keyword1")
&&
(Customer.Forenames.Contains("keyword2") || Customer.Surname.Contains("keyword2")
&&
(Customer.Forenames.Contains("keyword3") || Customer.Surname.Contains("keyword3")
);
しかし、検索語の任意のリストを処理したいと考えています。私はどこまでも
Func<Customer, bool> predicate = /* predicate */;
foreach(var token in tokens) {
predicate = (customer
=> predicate(customer)
&&
(customer.Forenames.Contains(token) || customer.Surname.Contains(token));
}
それは StackOverflowException を生成します-おそらく、割り当ての RHS の predicate() が実際には実行時まで評価されず、その時点で自分自身を呼び出すことになるためです...または何か。
要するに、2 つの述語が指定された場合に、指定された演算子を使用して 2 つのソース述語を構成する単一の述語を返す手法が必要ですが、Linq-to-SQL で明示的にサポートされている演算子に限定されます。何か案は?