Это субъективно / вопрос мнения, но вы можете вернуть свой репозиторий IQueryable<T>
, тогда вы можете выполнять «сложные запросы» в вашем сервисе следующим образом:
return _repository // IRepository<T>
.Find() // IQueryable<T>
.Where(someComplexPredicate) // IQueryable<T>
.SingleOrDefault(); // T
ObjectSet<T>
: IQueryable<T>
, что делает это возможным.
Если вы хотите начать делать ObjectSet<T>
специфические вещи в вашем сервисе, у вас есть два варианта:
- Предоставьте
ObjectSet<T>
-специфический метод в качестве метода в интерфейсе репозитория
- Используйте метод расширения
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-специфичные вещи должны быть сделаны с помощью методов расширения. Общие вещи можно сделать через интерфейс хранилища.