I think I\'m going in circles.
I\'m working on an MVC 3 solution using EF4 & POCOs (database-first) and IoC. My repository and UoW patterns were mostly adopted
Entity framework is a repository by itself. Why add an extra layer of complexity (repository). It just makes querying more difficult and you have to write all the repetitive code again and again (FindById(), FindAll(), FindAllByName() ....)
This is subjective/matter of opinion, but you could make your Repository return IQueryable<T>
, then you can do your "complex queries" in your service like this:
return _repository // IRepository<T>
.Find() // IQueryable<T>
.Where(someComplexPredicate) // IQueryable<T>
.SingleOrDefault(); // T
ObjectSet<T>
: IQueryable<T>
, which makes this possible.
If you want to start doing ObjectSet<T>
-specific things in your service, you've got two options:
ObjectSet<T>
-specific method as a method on your Repository interfaceIQueryable<T>
extension method to do a "soft cast" to ObjectSet<T>
(e.g var objSet = source as ObjectSet<T>
).Always try and go with option 1.
Perfect example is eager loading. There is a method called Include
on the ObjectContext<T>
, so if you use IQuerayable<T>
in your Repository, how do you eager load?
Since Include
takes a "magic string", you could accept this in your Find
method on your Repository, e.g:
return _repository // IRepository<T>
.Find("Product.Orders") // IQueryable<T>
.Where(someComplexPredicate) // IQueryable<T>
.SingleOrDefault(); // T
Fortunately in EF CTP5 they have introduced a strongly-typed Include
which works off IQueryable<T>
, so i didn't have to do the above when i cutover.
So as i said, best thing to do is expose methods on your Repository interface. But there needs to be a tradeoff - an interface should be a "contract" or "definition" of a service, not about the implmentation. So EF-specific things should be done via extension methods. General things can be done via the repository interface.