Реализация репозитория для EF4 с использованием DDD и IoC - PullRequest
5 голосов
/ 09 марта 2011

Я думаю, что я иду по кругу.

Я работаю над решением MVC 3 с использованием EF4 и POCO (сначала для базы данных) и IoC.Мой репозиторий и шаблоны UoW были в основном приняты из этой статьи и этой статьи .

Мое решение состоит из следующих проектов:

Реализации:

  • Презентация (сайт MVC)
  • Доменные службы (бизнес-уровень)
  • Доменное хранилище (доступ к данным)
  • Доменный контекст (мой EF4edmx и сгенерированный контекст)
  • Доменные модели (мои EOC4 сгенерированные POCO)

Интерфейсы:

  • Интерфейсы доменных служб (интерфейсы бизнес-уровня)
  • Интерфейсы репозитория домена (интерфейсы доступа к данным)
  • Интерфейсы контекста домена (интерфейсы для сгенерированного контекста EF4)

И, наконец, проект IoC, который связывает все вместе.

Если вы заметили в этой первой статье, автор упоминает об удалении зависимости от ObjectSet из доменных служб.Это, я предполагаю, для проверки.Однако проблема заключается в том, что он препятствует выполнению сложных запросов от доменных служб, поскольку IObjectSet и IEnumerable (возвращаемые большинством методов в хранилище) не блокируют методы для сложных запросов.

это означает, что я должен делать свои сложные запросы в моем хранилище?Должен ли я отказаться от таких методов, как public T Single(Expression<Func<T, bool>> where), и придерживаться таких методов, как public T GetUserById(int id)?

Если это не так, то как мне выполнять сложные запросы , такие как в моемуровень обслуживания?

Глядя на схему моего решения выше и вопросы, которые у меня есть, я двигаюсь в правильном направлении или создаю проблемы для себя?

Заранее спасибо.

Ответы [ 2 ]

8 голосов
/ 09 марта 2011

Это субъективно / вопрос мнения, но вы можете вернуть свой репозиторий IQueryable<T>, тогда вы можете выполнять «сложные запросы» в вашем сервисе следующим образом:

return _repository // IRepository<T>
          .Find() // IQueryable<T>
          .Where(someComplexPredicate) // IQueryable<T>
          .SingleOrDefault(); // T

ObjectSet<T>: IQueryable<T>, что делает это возможным.

Если вы хотите начать делать ObjectSet<T> специфические вещи в вашем сервисе, у вас есть два варианта:

  1. Предоставьте ObjectSet<T> -специфический метод в качестве метода в интерфейсе репозитория
  2. Используйте метод расширения IQueryable<T>, чтобы выполнить «мягкое приведение» к ObjectSet<T> (например, var objSet = source as ObjectSet<T>).

Всегда пытайтесь использовать вариант 1.

Прекрасный пример - стремительная загрузка. В ObjectContext<T> есть метод, называемый Include, поэтому, если вы используете IQuerayable<T> в своем репозитории, как вы стремитесь загрузить?

Поскольку Include принимает "волшебную строку", вы можете принять это в своем методе Find в своем репозитории, например:

return _repository // IRepository<T>
          .Find("Product.Orders") // IQueryable<T>
          .Where(someComplexPredicate) // IQueryable<T>
          .SingleOrDefault(); // T

К счастью, в EF CTP5 они ввели строго типизированный Include, который работает с IQueryable<T>, поэтому мне не нужно было делать вышеизложенное при переключении.

Итак, как я уже сказал, лучшее, что нужно сделать, - это открыть методы в интерфейсе вашего репозитория. Но должен быть компромисс - интерфейс должен быть «контрактом» или «определением» службы, а не о реализации. Так что EF-специфичные вещи должны быть сделаны с помощью методов расширения. Общие вещи можно сделать через интерфейс хранилища.

1 голос
/ 20 марта 2011

Entity Framework является хранилищем само по себе.Зачем добавлять дополнительный уровень сложности (хранилище).Это просто усложняет запросы, и вам приходится снова и снова писать весь повторяющийся код (FindById (), FindAll (), FindAllByName () ....)

...