Entity Framework — объединение приводит к «Невозможности создать постоянное значение типа ..»

#entity-framework #linq-to-entities

#entity-framework #linq-to-entities

Вопрос:

Чтобы выбрать все Scheduling , которые активны, у меня есть следующий код:

 var allSchedulesOnALine = CurrentUser.Lines.SelectMany(o => o.Scheduling).Where(o => o.Active);
var allSchedulesUnscheduled = Entities.SchedulingSet
    .Where(o => o.Line == null amp;amp; o.Site.Id == CurrentUser.Site.Id amp;amp;
           o.Factory == CurrentUser.Factory amp;amp; o.Active);

IEnumerable<Scheduling> allSchedules = allSchedulesUnscheduled.Union(allSchedulesOnALine);
foreach(Scheduling schedule in allSchedules.OrderBy(o => o.Ordering))
{
    //Do Stuff
}
  

( Factory является int )

Когда я запускаю этот код, я получаю эту загадочную ошибку в foreach строке:

Не удается создать постоянное значение типа ‘System.Коллекции.Общий.IEnumerable`1’. В этом контексте поддерживаются только примитивные типы (‘такие как Int32, String и Guid’).

Как ни странно, я могу перечислять оба allSchedulesOnALine и allSchedulesUnscheduled по отдельности. Еще более странно, если я изменю порядок объединения:

 IEnumerable<Scheduling> allSchedules = allSchedulesOnALine.Union(allSchedulesUnscheduled);
  

Это работает нормально!

У кого-нибудь есть идеи, почему это могло произойти? Я упускаю что-то важное, или это ошибка?

Я должен упомянуть, что я использую Entity Framework 3.5. EF4 в настоящее время для нас не подходит — это вне моего контроля :

Комментарии:

1. Я полагаю, что сообщение об ошибке указывает на то, что EF не может перевести ваш оператор union в SQL, но я не уверен, почему. Возможно ли, что CurrentUser.Lines.SelectMany(o => o.Scheduling).Where(o => o.Active) не используется отложенное выполнение? В таком случае это может объяснить, почему вы можете использовать его в одном направлении, но не в другом — одно выполняется в памяти, другое пытается полностью выполняться в SQL. Мысли?

Ответ №1:

Вы вызываете два разных метода с вашим «переупорядочением».

Вы не показываете типы allSchedulesOnALine или allSchedulesUnscheduled , но я уверен, что allSchedulesOnALine имеет тип IEnumerable<Schedule> и allSchedulesUnscheduled имеет тип IQueryable<Schedule> .

Итак, когда вы вызываете Queryable.Объединение, вы просите EF перевести выражение в SQL. Но передаваемый вами аргумент имеет тип IEnumerable<Schedule> , и он не может преобразовать это в запрос.

С другой стороны, когда вы вызываете Enumerable.Объединение, вы просите LINQ to Objects выполнить все это в памяти, что работает нормально, хотя, возможно, медленнее.

Итак, причина, по которой поведение отличается, заключается в том, что вы вызываете два совершенно разных метода, которые выполняют разные действия, но случайно имеют одинаковое имя. Нет, это не ошибка.

Комментарии:

1. Это, должно быть, десятый раз, когда вы помогаете мне с проблемой EF здесь, включая, я думаю, эту точную проблему раньше (тьфу). Еще раз спасибо, Крейг!