Entity Framework - метод "Все" - PullRequest
8 голосов
/ 19 мая 2009

Метод All должен оценивать аргумент для всех элементов в списке. Он работает нормально в обычном Linq, но когда я пытаюсь использовать его с EF, он выдает ошибку (" Невозможно создать постоянное значение типа 'Тип закрытия'. Только типы примитивов (например, Int32, String и Guid) поддерживается в этом контексте.")

Пример:

var myList = from person in entities.People
             where searchList.All(arg => arg == arg).ToList();

(arg == arg вот только для иллюстрации моего вопроса)

В моем сценарии searchList - это список, содержащий элементы поиска, такие как «Джон», «Бухгалтерский учет», «75». В моем EF-запросе я хочу получить все записи в People, в которых John, Accounting и 75 появляются в некоторых указанных полях для поиска. Более реалистичным примером будет что-то вроде этого:

where SearchList.All((person.FirstName + " " + person.LastName + " " + person.DepartmentName + " " + person.Phone).Contains)

Второй пример также хорошо работает с Linq в памяти, но EF это не нравится.

Пожалуйста, помогите! Что я могу сделать, чтобы это работало?

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

Пример кода:

IEnumerable<string> searchList = ParseSearchText(searchText); //search text is broken into search tokens - each token is an element in searchList. For instance "John", "Sales", "654"

var peopleQuery = from person in entities.vSearchPeople
where upperSearchList.All((person.FirstName + " " + person.Lastname + " " + person.Phone).ToUpperInvariant().Contains)
select person;

Ответы [ 2 ]

13 голосов
/ 19 мая 2009

Entity Framework поддерживает не все запросы. Это становится очевидным, если вы думаете о чем-то вроде следующего

dataContext.Persons.Where(person => MyMethod(person));

с MyMethod(), возвращающим логическое значение. Метод может делать все, и вы не можете перевести все на SQL. Решение состоит в том, чтобы получить все объекты в локальную память, используя ToList(), а затем использовать LINQ to Object.

dataContext.Persons.ToList().Where(person => MyMethod(person));

От вашего фактического запроса зависит, можно ли его переписать, чтобы он мог быть преобразован в SQL с помощью Entity Framework или если вам нужно выполнить запрос в локальной памяти, используя LINQ to Object.

Исключение, которое вы упомянули, звучит так, будто вы пытаетесь сделать что-то вроде следующего.

Company company = datacontext.Companies.Where(company.Name == "ACME").Single();

dataContext.Employees.Where(employee => employee.Company == company);

LINQ to Entity не поддерживает выражения, содержащие сущности, поэтому сравнение Company сущностей недопустимо. В этом случае вы можете переписать его следующим образом.

dataContext.Employees.Where(employee => employee.Company.Id == company.Id);

При этом сравниваются только идентификаторы - примитивный тип, такой как целое число или GUID, - и его можно преобразовать в SQL.

Пример поиска слово за словом (см. Также комментарии)

IQueryable<People> result = entities.People;

foreach (String item in searchList)
{
    // This copy is important in order not to modify the closure.
    String itemCopy = item;

    result = result.Where(p =>
        p.FirstName.ToUpper().Contains(itemCopy) ||
        p.LastName.ToUpper().Contains(itemCopy) ||
        p.Phone.ToUpper().Contains(itemCopy));
}

Это создаст запрос слово за словом. Отмечено, что Entity Framework распознает ToUpper(), ToLower() и Contains() (и некоторые другие) - поэтому я был строг, когда сказал, что Entity Framework не распознает вызовы методов. Да, но не много и не ToUpperInvariant() и ToLowerInvariant(). Кроме того, этот запрос преобразуется в CHARINDEX() вызовов функций с использованием параметров сортировки столбца, поэтому поиск может выполняться без учета регистра без явных вызовов ToUpper() или ToLower().

0 голосов
/ 15 марта 2017

Это хороший пример того, как хорошо работает метод All ().

model.ReferenceList = db.JournalCardReference.OrderBy(a => a.orderF)
 .Include(x => x.JournalCardField)
  .Where(x => x.JournalCardField
    .All(f => f.deleted == null || f.deleted != true)).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...