LINQ to Entities: Почему я не могу использовать метод Split как условие? - PullRequest
4 голосов
/ 30 августа 2009

У меня следующий запрос LINQ:

var aKeyword = "ACT";
var results = from a in db.Activities
              where a.Keywords.Split(',').Contains(aKeyword) == true
              select a;

Ключевые слова - это поле, разделенное запятыми.

Каждый раз, когда я запускаю этот запрос, я получаю следующую ошибку:

"LINQ to Entities не распознает метод 'Boolean Contains [String] (System.Collections.Generic.IEnumerable`1 [System.String], System.String)', и этот метод не может быть переведен в выражение магазина. "

Какая альтернатива тому, что я пытаюсь сделать?

Ответы [ 4 ]

8 голосов
/ 30 августа 2009

Ваша проблема в том, что LINQ-to-Entites должен перевести все, что вы ему даете, в SQL для отправки в базу данных.

Если это действительно то, что вам нужно сделать, вам придется заставить LINQ-to-Entities отозвать все данные и LINQ-to-Objects для оценки состояния.

Ex:

var aKeyword = "ACT";
var results = from a in db.Activities.ToList()
              where a.Keywords.Split(',').Contains(aKeyword) == true
              select a;

Имейте в виду, что это приведет к откату всех объектов из таблицы действий. Альтернативой может быть позволить БД выполнить первоначальный фильтр, а затем отфильтровать оставшуюся часть пути:

var aKeyword = "ACT";
var results = (from a in db.Activities
              where a.Keywords.Contains(aKeyword)
              select a).ToList().Where(a => a.KeyWords.Split(',').Contains(aKeyword));

Это позволит LINQ-to-Entities выполнять фильтр, который он понимает (string.Contains становится похожим запросом), который отфильтрует некоторые данные, а затем применит реальный фильтр, который вы хотите, через LINQ-to-Objects, как только вы получите объекты назад. Вызов ToList () заставляет LINQ-to-Entities выполнять запрос и создавать объекты, позволяя LINQ-to-Objects быть механизмом, выполняющим вторую часть запроса.

2 голосов
/ 31 августа 2009

В ответ на ваши соображения по поводу производительности для большого набора данных:

Вы собираетесь выполнять неиндексированное сопоставление строк с подстановочными символами на клиенте, так что да, произойдет потеря производительности.

Есть ли причина, по которой у вас есть несколько ключевых слов в одном поле таблицы? Вы можете нормализовать это, чтобы иметь таблицу ActivityKeywords, где для каждого действия у вас есть несколько записей ключевых слов.

Операции (action_id, ... / * удалить поле ключевых слов * /) ---> ActivityKeywords (Activity_id, keyword_id) ---> Ключевые слова (ключевое слово_id, значение)

Выезд Не первая нормальная форма: http://en.wikipedia.org/wiki/Database_normalization

РЕДАКТИРОВАТЬ: Кроме того, даже если вы придерживались одного столбца, есть способ сделать все на стороне сервера (если у вас строгий синтаксис: 'keyword1, keyword2, ..., keywordN'):

var aKeyword = "ACT";
var results = (from a in db.Activities
              where a.Keywords.Contains("," + aKeyword) || a.Keywords.Contains(aKeyword + ",")
              select a;
0 голосов
/ 31 августа 2009

Возможно, вы захотите взглянуть на этот вопрос о L2E и. Содержит решение, которое должно быть более эффективным, чем угадывание надмножества перед фильтрацией на стороне клиента.

0 голосов
/ 30 августа 2009

Я думаю, ты звонишь в Сплит. Это должно занять массив. Возможно, в Linq есть еще один Split, который находит и выдаёт вам необычную ошибку:

Это работает для Linq to Objects:

 var dataStore = new List<string>
                    {
                        "foo,bar,zoo",
                        "yelp,foo",
                        "fred",
                        ""
                    };
 var results = from a in dataStore
               where a.Split(new[] {','}).Contains("foo")
               select a;

 foreach (var result in results)
 {
     Console.WriteLine("Match: {0}", result);
 }

Выводит следующее:

Match: foo,bar,zoo
Match: yelp,foo

На самом деле, думая об этом, вам вообще нужен раскол? a.Contains("foo") может быть достаточно для вас (если вы не хотите нажимать foobar).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...