本文介绍了递归地(?)将LINQ谓词合成为一个谓词的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(编辑:我问了错误的问题,我遇到的真正的问题是在 - 但是这个问题得到了一些很好的答案,所以我把它留下了! p>

给出以下搜索文本:

 keyword1 keyword2 keyword3 ... keywordN

我想结束以下SQL:

  SELECT [columns] FROM Customer 
WHERE
(Customer.Forenames LIKE'%keyword1%')或Customer.Surname LIKE'%keyword1%' )
AND
(Customer.Forenames LIKE'%keyword2%'或Customer.Surname LIKE'%keyword2%')
AND
(Customer.Forenames LIKE'%keyword3%' OR Customer.Surname LIKE'%keyword3%')
AND
...
AND
(Customer.Forenames LIKE'%keywordN%'or Customer.Surn ame 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令牌){
predicate = (客户
=>谓词(客户)
&&
(customer.Forenames.Contains(token)|| customer.Surname.Contains(token));
}

产生一个StackOverflowException - 可能是因为在t的RHS上的predicate他的任务直到运行时才被实际评估,此时它最终会自动调用自己......或者什么。

总之,我需要一种技术,谓词将返回一个谓词,它由一个提供的运算符组成两个源谓词,但仅限于Linq-to-SQL明确支持的运算符。任何想法?

解决方案

我会建议另一种方法

做:

  var query = dataContext.Customers; 

然后,在一个循环中执行

<$ (关键字)中的字符串关键字
{
query = query.Where(Customer.Forenames.Contains(keyword)|| Customer.Surname.Contains(keyword) );
}


(EDIT: I have asked the wrong question. The real problem I'm having is over at Compose LINQ-to-SQL predicates into a single predicate - but this one got some good answers so I've left it up!)

Given the following search text:

"keyword1 keyword2 keyword3   ... keywordN"

I want to end up with the following 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%')

Effectively, we're splitting the search text on spaces, trimming each token, constructing a multi-part OR clause based on each token, and then AND'ing the clauses together.

I'm doing this in Linq-to-SQL, and I have no idea how to dynamically compose a predicate based on an arbitrarily-long list of subpredicates. For a known number of clauses, it's easy to compose the predicates manually:

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")
);

but I want to handle an arbitrary list of search terms. I got as far as

Func<Customer, bool> predicate = /* predicate */;
foreach(var token in tokens) {
    predicate = (customer 
        => predicate(customer) 
        && 
         (customer.Forenames.Contains(token) || customer.Surname.Contains(token));
}

That produces a StackOverflowException - presumably because the predicate() on the RHS of the assignment isn't actually evaluated until runtime, at which point it ends up calling itself... or something.

In short, I need a technique that, given two predicates, will return a single predicate composing the two source predicates with a supplied operator, but restricted to the operators explicitly supported by Linq-to-SQL. Any ideas?

解决方案

I would suggest another technique

you can do:

var query = dataContext.Customers;

and then, inside a cycle do

foreach(string keyword in keywordlist)
{
    query = query.Where(Customer.Forenames.Contains(keyword) || Customer.Surname.Contains(keyword));
}

这篇关于递归地(?)将LINQ谓词合成为一个谓词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-26 23:55