В спорном сообщении в блоге Сегодня хакерская атака рассуждает о том, что, по всей видимости, является ошибкой в новой платформе LINQ To Entities:
Допустим, я ищу покупателя:
var alice = data.Customers.First( c => c.Name == "Alice" );
Хорошо, это прекрасно работает. А теперь посмотрим, найду ли я один из ее заказов:
var order = ( from o in alice.Orders where o.Item == "Item_Name" select o ).FirstOrDefault();
LINQ-to-SQL найдет дочернюю строку. LINQ-to-Entities ничего не возвращает.
Теперь предположим, что я перебираю все заказы в базе данных:
foreach( var order in data.Orders ) { Console.WriteLine( "Order: " + order.Item ); }
А теперь повтори мой поиск:
var order = ( from o in alice.Orders where o.Item == "Item_Name" select o ).FirstOrDefault();
Вау! LINQ-to-Entities внезапно сообщает мне, что дочерний объект существует, несмотря на то, что ранее я сказал, что его не было!
Моя первоначальная реакция заключалась в том, что это должна быть ошибка, но после дальнейшего рассмотрения (и поддержанный командой ADO.NET), я понял, что такое поведение было вызвано тем, что Entity Framework не загружала подзапрос «Заказы» с ленивой загрузкой, когда Алиса извлекается из контекста данных.
Это потому, что заказ - это запрос LINQ-To-Object:
var order = ( from o in alice.Orders
where o.Item == "Item_Name"
select o ).FirstOrDefault();
И никаким образом не обращается к тексту данных, в то время как его цикл foreach:
foreach( var order in data.Orders )
Осуществляет доступ к тексту данных.
LINQ-To-SQL фактически создавал ленивые загружаемые свойства для заказов, так что при обращении к ним выполнялся другой запрос, LINQ to Entities оставляет вам возможность вручную извлекать связанные данные.
Я не большой поклонник ORM, и именно в этом причина. Я обнаружил, что для того, чтобы все данные, которые вы хотите, были у вас под рукой, они многократно выполняют запросы за вашей спиной, например, указанный выше запрос linq-to-sql может запускать дополнительный запрос для каждой строки клиентов для получения заказов. .
Однако то, что EF этого не делает, по-видимому, в значительной степени нарушает принцип наименьшего удивления. Хотя это технически правильный способ делать что-то (вы должны запустить второй запрос для получения заказов или получить все из представления), он не ведет себя так, как вы ожидаете от ORM.
Итак, это хороший дизайн фреймворка? Или Microsoft слишком много думает об этом за нас?