Мне сложно определить лучший способ справиться с этим ... С Entity Framework (и L2S) запросы LINQ возвращают IQueryable. Я прочитал различные мнения о том, должен ли DAL/BLL возвращать IQueryable, IEnumerable или IList. Предполагая, что мы идем с IList, запрос выполняется сразу и этот элемент управления не передается на следующий уровень. Это упрощает модульный тест и т. Д. Вы теряете возможность уточнения запроса на более высоких уровнях, но вы можете просто создать другой метод, который позволит вам уточнить запрос и вернуть IList. И есть еще много плюсов и минусов. Все идет нормально.IQueryable и lazy loading
Теперь идет платформа Entity Framework и ленивая загрузка. Я использую объекты POCO с прокси в .NET 4/VS 2010. В презентации слоя я делаю:
foreach (Order order in bll.GetOrders())
{
foreach (OrderLine orderLine in order.OrderLines)
{
// Do something
}
}
В этом случае GetOrders() возвращает IList, так что сразу выполняет, прежде чем вернуться к PL. Но в следующем foreach у вас есть ленивая загрузка, которая выполняет несколько SQL-запросов, поскольку она получает все OrderLines. Так что в основном PL выполняет SQL-запросы «по требованию» в неправильном слое.
Есть ли разумный способ избежать этого? Я мог бы отказаться от ленивой загрузки, но тогда в чем смысл иметь эту «особенность», которую все жаловались EF1, не было? И я признаю, что это очень полезно во многих сценариях. Поэтому я вижу несколько вариантов:
- Как-то удалить все ассоциации в сущности и добавить методы для их возврата. Это противоречит поведению EF по умолчанию/генерации кода и затрудняет выполнение некоторых запросов LINQ с несколькими объектами. Это похоже на шаг назад. Я голосую нет.
- Если у нас есть ленивая загрузка в любом случае, что затрудняет модульное тестирование, то зайдите полностью и верните IQueryable. У вас будет больше контроля над слоями. Я все еще не думаю, что это хороший вариант, потому что IQueryable связывает вас с L2S, L2E или с вашей собственной полной реализацией IQueryable. Ленивая загрузка может запускать запросы «по требованию», но не привязывает вас к какому-либо конкретному интерфейсу. Я голосую нет.
- Отключить ленивую загрузку. Вам придется обрабатывать свои ассоциации вручную. Это может быть с нетерпением загрузки .Include(). Я проголосовал «да» в некоторых конкретных случаях.
- Держите IList и ленивую загрузку. Во многих случаях я голосую «да», только из-за проблем с остальными.
Любые другие варианты или предложения? Я не нашел вариант, который действительно убеждает меня.
Вы не покрывал «отложенной загрузки/выполнение SQL от слоя пользовательского интерфейса», но это все еще помогает. Я думаю, что последний фрагмент кода ближе всего к тому, что я ищу. Кажется, что у вас 1) простота использования, 2) инкапсуляция/SoC/unit-testable/etc., 3) возможность использования расширенных функций (загружаемая загрузка и т. Д.). Выбери два. У вас не может быть всех троих. В любом случае, спасибо за вашу помощь. –