ССЫЛКА на объекты:Почему я не могу использовать метод разделения в качестве условия?

StackOverflow https://stackoverflow.com/questions/1354723

Вопрос

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

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

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

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

"LINQ to Entities не распознает метод 'Boolean Содержит[строку](System.Коллекции.Универсальный.IEnumerable`1[System.Строка], Системный.String)' метод, и этот метод не может быть преобразован в выражение хранилища".

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

Это было полезно?

Решение

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

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

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

Действия (activity_id, .../* удалить поле ключевых слов */) ---> ActivityKeywords(activity_id, keyword_id) ---> Ключевые слова (keyword_id, значение)

Проверьте Не первую обычную форму: http://en.wikipedia.org/wiki/Database_normalization

Редактировать:Кроме того, даже если бы вы придерживались одного столбца, есть способ сделать все на стороне сервера (если у вас строгий синтаксис:'ключевое слово1, ключевое слово2, ..., ключевое слово'):

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

Другие советы

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

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

Бывший:

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

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

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 быть механизмом, который выполняет вторую часть запроса.

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

Это работает для Linq к объектам:

 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).

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top