LINQ: Как переписать предложение WHERE, чтобы избежать: Локальная последовательность не может быть использована в LINQ to SQL - PullRequest
2 голосов
/ 18 ноября 2011

Мой запрос 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 ]

1 голос
/ 18 ноября 2011

Как говорится в сообщении об ошибке, поддерживается только содержимое. Ваш список превратился в предложение 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));
}

Редактировать: Взять локальную копию строки, чтобы, надеюсь, обойти проблему с областью видимости в лямбде Скомпилировано в моей голове в 17:00 в пятницу, мои извинения, если это все еще не правильно:)

1 голос
/ 18 ноября 2011

Я думаю, что простым способом могло бы быть выполнение запроса к объектам вместо его передачи в SQL.

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

Это не лучший показатель производительности, но он зависит от размера источника данных.

1 голос
/ 18 ноября 2011

Я полагаю Вы можете отправить список строк в 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;  

Это довольно ужасно, но если у вас есть только несколько строк, это может сработать.

Обновление : Чтобы объяснить, как работает цикл 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"))

Это еще не выполнено - это просто дерево выражений - но Where был помечен для исходного запроса.

Второй - "Мир", и к нему добавляется выражение

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

Это не то же самое, что «Содержит Hello && World», но оно логически эквивалентно - product будет проверено на наличие «Hello», а если будет, то будет проверено на наличие если он содержит «Мир». Он должен содержать оба, чтобы «пройти».

Объединение таких выражений точно такое же, как и для объединения строк.

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

Значение result не будет "o". Это будет «Привет».

...