Я не знаю, является ли это ошибкой, и если и почему это ожидается в LINQ to SQL.Я могу ответить на ваш последний вопрос только в том случае, если это также произойдет с Entity Framework.
Ответ: Нет.
С EF вы должны использовать синтаксис инициализатора объекта, хотя при создании экземпляра Entry
объекты.Использование конструктора по умолчанию приводит к исключению:
var resultQuery = (
from x in dc.SomeTable
select new Set
{
Field = new Entry { Name = "X" },
Property = new Entry { Name = "X" }
}
);
Не имеет значения, как вы инициализируете.Используя приведенный выше код (и с 4 строками в небольшой тестовой таблице), я получаю вывод с вашей тестовой программой:
False
False
4
False
False
False
10
False
Похоже, что существует большая разница между LINQ to SQL и Entity Framework в отношении объектаматериализация во время проекций.
(я тестировал с EF 4.1 / DbContext.)
Edit
Если я возьму измененный запрос в моем кодеприведенный выше фрагмент также для вашего запроса LINQ to SQL и просмотра сгенерированного SQL. Я получаю следующее:
SELECT NULL AS [EMPTY]
FROM [dbo].[SomeTable] AS [t0]
Тогда как то же самое с LINQ to Entites создает этот запрос:
SELECT
1 AS [C1],
N'X' AS [C2],
N'X' AS [C3]
FROM [dbo].[SomeTable] AS [Extent1]
Моя интерпретациязаключается в том, что LINQ to SQL анализирует код проекции и запрашивает только столбцы для значений свойств, которые зависят от «переменной строки» x.Все остальные свойства заполняются на клиенте, когда объекты материализуются.Если объект вообще не зависит от значения столбца, LINQ to SQL создает один постоянный объект и повторно использует его во всей коллекции результатов.
В отличие от этого Entity Framework также отправляет постоянные значения (независимо от x) к серверу базы данных.Значения отправляются обратно клиенту, и EF обрабатывает эти значения, как если бы они были значениями столбцов, и обновляет свойства объектов в проекции.
Это также приводит к большой разнице в том, что нечто подобное ...
Random random = new Random();
var resultQuery = (
from x in dc.SomeTable
select new Set
{
Field = new Entry { ID = random.Next() },
Property = new Entry { Name = "X" }
}
);
... работает в LINQ to SQL, потому что, по-видимому, случайное значение функции (которое не зависит от x) вычисляется на клиенте и затем присваивается свойству.Но EF хочет перевести правую часть присваивания свойства в SQL и отправить его в виде фрагмента SQL на сервер базы данных, что приводит к ошибке и приводит к печально известному « ... не может быть преобразовано в выражение хранилища ... "исключение.
Редактировать 2
Кстати: последний фрагмент кода выше все еще создает только один экземпляр Field
во всей коллекции: random.Next()
оценивается толькоOnce (а также конструктор Entry
вызывается только один раз для объекта Field
).Теперь это действительно сбивает с толку, поскольку при написании такого кода можно ожидать, что вы хотите иметь случайное значение для каждой строки, возвращаемой из базы данных.Это не тот случай.