LINQ:如何重写WHERE子句以避免:本地序列不能在LINQ to SQL中使用

时间:2011-11-18 03:26:42

标签: asp.net linq linqdatasource

我的Linq查询给出错误: 本地序列不能用于查询运算符的LINQ to SQL实现,但Contains运算符

 var query = from product in dc.catalog
              where TextBox1.Text.Split(' ').All(s => product.Name.Contains(s))
              select product;

如何重写以避免此错误?

3 个答案:

答案 0 :(得分:1)

相信您可以向contains的LINQ-to-SQL发送字符串列表。

我错了。但你可以做的是制定一个巨大的Where条款。如果要比较很多字符串,我不建议这样做,但要测试一下。

var strings = TextBox1.Text.Split(' ').ToList();
var query = from product in dc.catalog select product;
foreach (var s in strings)
{
    query = query.Where(product => product.Name.Contains(s));
}
return query;

这将创建类似

的内容
 var query = from product in dc.catalog
             where product.Name.Contains(string1)
             where product.Name.Contains(string2)
             where product.Name.Contains(string3)
             // etc
             select product;  

这非常可怕,但如果你只有一些字符串可能会这样做。

更新:要解释foreach循环的工作原理,请考虑原始查询

 from product in dc.catalog select product

让我们说你的文本框包含" Hello World"。我将其拆分为{ "Hello", "World" }之类的列表,然后迭代列表。

列表中的第一个是" Hello"。行query = query.Where(product => product.Name.Contains(s));使表达式变为

from product in dc.catalog select product
.Where(product => product.Name.Contains("Hello"))

它尚未执行 - 它只是一个表达式树 - 但Where已被标记为原始查询。

第二个是" World",并附加表达式

from product in dc.catalog select product
.Where(product => product.Name.Contains("Hello"))
.Where(product => product.Name.Contains("World"))

这与&#34相同;包含Hello&& World",但它在逻辑上是等价的 - product将被测试以查看它是否包含" Hello",如果确实如此,那么它将被测试以查看它是否包含&# 34;世界&#34 ;.它必须同时包含“传递”。

像这样连接表达式与连接字符串完全相同。

var letters = new List<string>(){ "H", "e", "l", "l", "o" };
string result = ""
foreach (var letter in letters)
{
    result = result + letter;
}

result的值不会是&#34; o&#34;。它将是&#34;你好&#34;。

答案 1 :(得分:1)

如错误所示,仅支持包含。您的列表变成了SQL IN子句 为了做你想做的事情,你将需要依赖LINQ提供的延迟执行,并建立一个LINQ语句来检查名称中的每个单词。

var query = dc.catalog.AsQueryable();
foreach(var s in TextBox1.Text.Split(' ') {
  string copy = s;  // Take a local copy of the string. Lambda's inside loops are fun!
  query= query.Where(product => product.Name.Contains(copy));
}

编辑:获取字符串的本地副本,希望能够解决lambda上的范围问题。星期五下午5点在我的头脑中编辑,如果它仍然不对,我道歉:)

答案 2 :(得分:1)

我认为一种简单的方法是在对象上执行查询,而不是将其传输到SQL。

var query = from product in dc.catalog.ToList()
              where TextBox1.Text.Split(' ').All(s => product.Name.Contains(s))
              select product;

它在性能方面不是最好的,但它取决于数据源的大小。