EF4: Почему создание прокси должно быть включено, когда включена ленивая загрузка?

У меня есть проект, структурированный следующим образом: .Persistence → .Repo → .Services → .Controllers → MVC3 App.

Каждый слой имеет соответствующую сборку с интерфейсами, а также некоторые другие сборки, такие как .Entities,.ViewModels и общие сборки кода.

Настойчивость. В этом случае используется файл данных EF4 (первый код) и ссылка на EF4.3. Там factory для создания Контекста, называемого GetContext(), и этот factory реализует IDisposable. Это НЕ единственная причина, по которой я подумал, что виндзор сделает для меня LifestyleSingleton().
Репо - это хранилища, реализующие шаблон репозитория и спецификации (http://huyrua.wordpress.com/2010/07/13/entity-framework-4-poco-repository-and-specification-pattern/).

Другие слои самоочевидны...

Вопросы:
 1. Почему создание прокси-сервера должно быть включено, когда включена ленивая загрузка?
 2. Если я хочу установить lazyloading = false, могу ли я включить IEnumerable в Service layer в ObjectQuery, чтобы использовать .Include() там?

Ответ 1

Почему создание прокси-сервера должно быть включено, когда включена ленивая загрузка?

Поскольку ленивая загрузка с помощью POCOs зависит от создания прокси. Без прокси ленивая загрузка не работает. Поэтому комбинация ProxyCreationEnabled = false и LazyLoadingEnabled = true не имеет смысла. Обратная комбинация имеет смысл, если вы хотите работать с прокси-серверами отслеживания изменений, но не хотите использовать ленивую загрузку.

Если я хочу установить lazyloading = false, могу ли я использовать IEnumerable в Service layer для ObjectQuery, чтобы использовать .Include() там?

Это зависит от того, каков ваш IEnumerable<T>. Если это результат ToList(), тогда no (потому что List<T> является реализацией IEnumerable<T>, но не IQueryable<T>.). Если вы просто вернете IQueryable<T> как IEnumerable<T>, вы, вероятно, можете применить к IQueryable<T>. (В EF 4.3 вы использовали бы IQueryable<T> или DbQuery<T>, а не ObjectQuery<T>.)

Но, несмотря на то, что потребность в подобном приведении указывает на то, что в вашей архитектуре что-то не так. Использование Include является модификацией запроса. Если вашему уровню обслуживания разрешено изменять запросы, ваш репозиторий должен возвращать IQueryable<T> - этот тип предназначен для создания и изменения запросов.

Если ваш репозиторий не должен возвращать IQueryable<T>, вы должны передать выражение или спецификацию методам репозитория, которые используются для добавления Include к вашему запросу, - внутри метода репозитория, а не в службе слой.