Entity Framework - " не удалось создать постоянное значение типа 'Closure type'... " ошибка


почему я получаю ошибку:

невозможно создать постоянное значение типа "Тип закрытия". Только примитивные типы (например Int32, String и Guid) поддерживаются в этот контекст.

когда я пытаюсь перечислить следующий запрос Linq?

IEnumerable<string> searchList = GetSearchList();
using (HREntities entities = new HREntities())
{
   var myList = from person in entities.vSearchPeople
   where upperSearchList.All( (person.FirstName + person.LastName) .Contains).ToList();
}

обновление: Если я попробую следующее, чтобы попытаться изолировать проблему, я получаю ту же ошибку:

where upperSearchList.All(arg => arg == arg) 

Так что, похоже, проблема со всеми метод, верно? Есть предложения?

4 78

4 ответа:

похоже, вы пытаетесь сделать эквивалент "WHERE...IN-состояние. Проверьте Как написать запросы стиля "где в" с помощью LINQ to Entities для примера того, как сделать этот тип запроса с помощью LINQ to Entities.

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

Я провел последние 6 месяцев, борясь с этим ограничением с EF 3.5, и хотя я не самый умный человек в мире, я уверен, что у меня есть что-то полезное, чтобы предложить по этой теме.

SQL, созданный путем выращивания 50-мильного дерева выражений "или стиля", приведет к плохому плану выполнения запроса. Я имею дело с несколькими миллионами строк и влияние является существенным.

есть небольшой хак, который я нашел, чтобы сделать SQL 'in', который помогает, если вы просто ищете для группы объектов по идентификатору:

private IEnumerable<Entity1> getByIds(IEnumerable<int> ids)
{
    string idList = string.Join(",", ids.ToList().ConvertAll<string>(id => id.ToString()).ToArray());
    return dbContext.Entity1.Where("it.pkIDColumn IN {" + idList + "}");
}

где pkIDColumn-это имя столбца идентификатора первичного ключа таблицы Entity1.

НО ПРОДОЛЖАЙТЕ ЧИТАТЬ!

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

Если бы у меня было больше времени, я бы попытался представить это визуально, но я не так просто изучите это предложение на мгновение: рассмотрим схему с таблицами Person, GovernmentId и GovernmentIdType. Эндрю Тапперт (человек) имеет два удостоверения личности (GovernmentId), один из Орегона (GovernmentIdType) и один из Вашингтона (GovernmentIdType).

Теперь создайте edmx из него.

Это может быть достигнуто с помощью одной базы данных хит с это:

dbContext context = new dbContext();
string idValue = "1234567";
Expression<Func<Person,bool>> expr =
    person => person.GovernmentID.Any(gid => gid.gi_value.Contains(idValue));

IEnumerable<Person> people = context.Person.AsQueryable().Where(expr);

вы видите здесь подзапрос? Сгенерированный sql будет использовать "соединения" вместо подзапросов, но эффект тот же. В эти дни SQL server оптимизирует подзапросы в объединения под обложками в любом случае, но в любом случае...

ключ к этой работе является .Внутри выражения.

Я нашел причину ошибки (я использую фреймворк 4.5). Проблема в том, что EF сложный тип, который передается в параметре "Contains", не может быть переведен в SQL-запрос. EF может использовать в SQL-запросе только простые типы, такие как int, string...

this.GetAll().Where(p => !assignedFunctions.Contains(p))

GetAll предоставляет список объектов со сложным типом (например: "функция"). Поэтому я бы попытался здесь получить экземпляр этого сложного типа в моем SQL-запросе, который, естественно, не может работай!

Если я могу извлечь из моего списка, параметры, которые подходят для моего поиска, я могу использовать:

var idList = assignedFunctions.Select(f => f.FunctionId);
this.GetAll().Where(p => !idList.Contains(p.FunktionId))

теперь EF больше не имеет сложного типа "функция" для работы, но, например, с простым типом (long). И это прекрасно работает!

Я получил это сообщение об ошибке, когда мой объект массив, который используется в .Все функции имеют значение null После того, как я инициализировал объект массива (upperSearchList в вашем случае), ошибка исчезла Сообщение об ошибке было введено в заблуждение в этом случае

где upperSearchList.Все (arg = > человек.someproperty.StartsWith (arg)))