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

发布于 2024-12-16 16:23:23 字数 295 浏览 1 评论 0原文

我的 Linq 查询出现错误:本地序列不能在除 Contains 运算符之外的查询运算符的 LINQ to SQL 实现中使用

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

如何重写以避免此错误?

My Linq query gives the error: Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator

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

How can it be rewritten to avoid this error?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吃→可爱长大的 2024-12-23 16:23:23

正如错误所述,仅支持包含。您的列表变成了 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 点在我的脑海中编译,如果仍然不对,我深表歉意:)

As the error says, only contains is supported. Your list in turned into a SQL IN clause.
To do what you are after, you are going to need to rely on the deferred execution LINQ provides, and build up a LINQ statement that checks every word is in the name.

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

Edit: Taking a local copy of the string to hopefully get around the scoping issue on the lambda. Compiled in my head at 5pm on a Friday, my apologies if it still isn't right :)

耶耶耶 2024-12-23 16:23:23

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

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

就性能而言,它不是最好的,但它取决于数据源的大小。

I think a simple way could be executing the query on the objects, instead of transport it to the SQL.

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

It's not the best in terms of performance, but it depends on the size of the datasource.

怀里藏娇 2024-12-23 16:23:23

我相信您可以将字符串列表发送到 LINQ-to-SQL 以获得 contains

我错了。但您可以做的是创建一个巨大的 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;  

It's相当可怕的东西,但如果你只有几个字符串,它可能会这样做。

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

 from product in dc.catalog select product

假设您的文本框包含“Hello World”。我会将其拆分为 { "Hello", "World" } 之类的列表,然后迭代该列表。

列表中的第一个是“你好”。 query = query.Where(product => Product.Name.Contains(s)); 行导致表达式变为

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

It's notexecute Yet - 它只是一个表达式树 - 但 其中 已被标记到原始查询上。

第二个是“World”,并附加了表达式

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

这与“Contains Hello && World”读起来不同,但它在逻辑上是等效的 - 将测试product以查看它是否包含“Hello”,如果包含,则将测试它是否包含“World”。它必须包含两者才能“通过”。

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

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

result 的值不会是“o”。这将是“你好”。

I believe you can send a list of strings to LINQ-to-SQL for a contains.

I was wrong. But what you can do is make an enormous Where clause. I wouldn't recommend this if there are going to be a lot of strings to compare, but test and see.

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;

This will create something like

 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;  

It's pretty horrible, but if you only have a few strings it might do.

Update: To explain how the foreach loop works, consider the original query

 from product in dc.catalog select product

Let's say your textbox contains "Hello World". I'll split that into a list like { "Hello", "World" }, and then iterate the list.

First in the list is "Hello". The line query = query.Where(product => product.Name.Contains(s)); causes the expression to become

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

It's not executed yet - it's just an expression tree - but the Where has been tagged on to the original query.

Second is "World", and the expression is appended

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

This does not read the same as "Contains Hello && World", but it is logically equivalent - the product will be tested to see if it contains "Hello", and if it does then it will be tested to see if it contains "World". It has to contain both to 'pass'.

Concatenating expressions like this is exactly the same as concatenating strings.

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

The value of result will not be "o". It will be "Hello".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文