Ответ 1
На мой взгляд, важный вопрос здесь - отключить LazyLoading?
Если вы ничего не сделали, по умолчанию он включен.
Поэтому, когда вы выполняете Person.Pathway.Country
, вы будете вызывать другой вызов сервера базы данных (если только вы не хотите загрузиться, о чем я сейчас расскажу). Учитывая, что вы используете шаблон хранилища - это большой нет-нет. Контроллеры не должны вызывать прямые вызовы на сервере базы данных.
После того, как пользователь C получил информацию из M, он должен быть готов выполнить проецирование (если необходимо) и перейти на V, не возвращайтесь к M.
Вот почему в нашей реализации (мы также используем репозиторий, ef4 и единицу работы) мы отключим Lazy Loading и разрешаем пройти через навигационные свойства через наш сервисный уровень (a серии инструкций "Включить", сделанные слаще посредством перечислений и методов расширения).
Затем мы выполняем eager-load эти свойства, как того требуют контроллеры. Но важно то, что контроллер должен явно запросить их.
Что в основном говорит о пользовательском интерфейсе - "Эй, вы получаете только основную информацию об этом объекте. Если вам нужно что-нибудь еще, попросите его".
У нас также есть Service Layer, обеспечивающий посредничество между контроллерами и репозиторием (наши репозитории возвращаются IQueryable<T>
). Это позволяет репозиторию выйти из бизнеса обработки сложных ассоциаций. Желательная загрузка выполняется на уровне обслуживания (а также в таких вещах, как пейджинг).
Преимущество сервисного уровня прост - более свободная связь. Репозиторий обрабатывает только Add, Remove, Find (который возвращает IQueryable), Unit of Work обрабатывает "новички" DC и Commiting of changes, Service layer обрабатывает материализацию объектов в конкретные коллекции.
Это хороший, 1-1 стековый подход:
personService.FindSingle(1, "Addresses") // Controller calls service
|
--- Person FindSingle(int id, string[] includes) // Service Interface
|
--- return personRepository.Find().WithIncludes(includes).WithId(id); // Service calls Repository, adds on "filter" extension methods
|
--- IQueryable<T> Find() // Repository
|
-- return db.Persons; // return IQueryable of Persons (deferred exec)
Мы еще не встали на уровень MVC (мы делаем TDD), но уровень сервиса может быть другим местом, в котором вы могли бы гидратировать основные объекты в ViewModels. И снова - это будет до контроллера, чтобы решить, сколько информации он хочет.
Опять же, все о свободной связи. Ваши контроллеры должны быть максимально упрощенными и не должны беспокоиться о сложных ассоциациях.
Что касается количества репозиториев, это тема с высокой дискуссией. Некоторым нравится иметь по одному на сущность (overkill, если вы спросите меня), некоторым нравится группироваться на основе функциональности (имеет смысл с точки зрения функциональности, с ней легче работать), однако у нас есть один для каждого заполнителя.
Я могу только догадываться о вашей модели, что "Person" должен быть единственным агрегированным корнем, который я могу видеть.
Следовательно, не имеет смысла иметь другой репозиторий для обработки "Пути", когда путь всегда связан с конкретным "Лицом". Репозиторий Person должен обрабатывать это.
Опять же - возможно, если вы закроете свой EDMX, мы сможем дать вам больше советов.
Этот ответ может распространяться слишком далеко, основываясь на объеме вопроса, но подумал, что я дам подробный ответ, поскольку мы имеем дело с этим точным сценарием прямо сейчас.
НТН.