Объединение трех списков в один с LINQ вызывает исключение

Хорошо, я должен делать что-то немое, но разве это не должно работать? У меня есть три списка:

var commonViews = (from v in context.TPM_VIEWS where v.VIEWID < 0 select v); // IQueryable<TPM_VIEWS>
var ownedViews = (from v in context.TPM_VIEWS where v.OWNERID == userId && v.VIEWID > 0 select v); // IQueryable<TPM_VIEWS>
var sharedViews = (from v in context.TPM_USER.Include("TPM_VIEWS2") where v.USERID == userId select v).First().TPM_VIEWS2; // EntityCollection<TPM_VIEWS>

Каждый список имеет правильные значения и счетчик. Я могу вернуть любой из этих списков:

return commonViews.ToList();

И я могу вернуть любой из двух этих списков:

return commonViews.Concat(ownedViews).ToList();

Однако, когда я пытаюсь вернуть все три:

return commonViews.Concat(ownedViews).Concat(sharedViews).ToList();

Я получаю исключение:

Невозможно создать постоянное значение типа "Entity.TPM_VIEWS". Только в этом контексте поддерживаются примитивные типы или типы перечислений.

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

UPDATE:

Я на 93% уверен, что проблема здесь:

var sharedViews = (from v in context.TPM_USER.Include("TPM_VIEWS2") where v.USERID == userId select v).First().TPM_VIEWS2;

Это выглядит как перечислимый список объекта TPM_VIEWS, и я могу вызвать ToList() на нем и получить правильные данные, но он не очень хорошо работает с другими списками.

ОБНОВЛЕНИЕ 2:

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

commonViews.ToList().Concat(ownedViews.ToList()).Concat(sharedViews.ToList()).ToList();

Ответ 1

Проблема в том, что Concat() на EF IQueryable<T> превратит всю конкатенацию в один запрос.

Когда вы вызываете .Concat(sharedViews), вы передаете скалярную (предварительно загруженную) коллекцию вашего класса вложенных сущностей.
EF не знает, как преобразовать это в запрос, поэтому он жалуется.

Вы можете сделать это быстрее, вызывая AsEnumerable() вместо ToList().

Ответ 2

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

commonViews.ToList().Concat(ownedViews.ToList()).Concat(sharedViews.ToList()).ToList();

Это потому, что каждый из исходных запросов выполняется отдельно; вы только конкатенируете результаты в памяти. Кажется, что ошибка в трансляторе запросов Entity Framework при объединении трех запросов, но когда вы вызываете ToList для каждого из них, они больше не являются запросами EF, они просто списки, поэтому они объединены используя Linq to Objects.