views:

46

answers:

3

I'm studying MVC and EF at the moment and I see quite often in the articles on those subjects that controller manipulates data via a Repository object instead of directly using LINQ to Entities.

I created a small web application to test some ideas. It declares the following interface as an abstraction of the data storage

public interface ITinyShopDataService
{
    IQueryable<Category> Categories { get; }
    IQueryable<Product> Products { get; }
}

Then I have a class that inherits from the generated class TinyShopDataContext (inherited from ObjectContext) and implements ITinyShopDataService.

public class TinyShopDataService : TinyShopDataContext, ITinyShopDataService
{
    public new IQueryable<Product> Products
    {
        get { return base.Products; }
    }

    public new IQueryable<Category> Categories
    {
        get { return base.Categories; }
    }
}

Finally, a controller uses an implementation of ITinyShopDataService to get the data, e.g. for displaying products of a specific category.

public class HomeController : Controller
{
    private ITinyShopDataService _dataService;

    public HomeController(ITinyShopDataService dataService)
    {
        _dataService = dataService;
    }

    public ViewResult ProductList(int categoryId)
    {
        var category = _dataService.Categories.First(c => c.Id == categoryId);
        var products = category.Products.ToList();
        return View(products);
    }
}

I think the controller above possesses some positive properties.

  • It is easily testable because of data service being injected.
  • It uses LINQ statements that query an abstract data storage in an implementation-neutral way.

So, I don't see any benefit of adding a Repository between the controller and the ObjectContext-derived class. What do I miss? (Sorry, it was a bit too long for the first post)

A: 

What you're missing is the ability to update, create and delete objects. If that's not an issue, than the interface is probably good enough as it is (although I would let it derive from IDisposable to make sure you can always dispose the context (and test for this))

Sander Rijken
Ok, I stripped off everything non-essential and left only the lines that illustrate the idea that if I had created a Repository it would have consisted only of single- or two-line methods that would have hardly added any noticeable value.
Ivan Gerken
Ah, now I see what you're saying.. You're just extracting an interface from the DBContext, instead of using a repository to wrap it.
Sander Rijken
+2  A: 

Ayende of the NHibernate project and other fame agrees with you.

Some Domain Driven Design people would suggest that you should have a service (not same as web service) layer that is called from your controller, but DDD is usually applied to complex domains. In simple applications, what you're doing is fine and testable.

Tim Hoolihan
+4  A: 

You can test your controllers just fine with what you propose.

But how do you test your queries inside the data service? Imagine you have very complicated query behavior, with multiple, complex queries to return a result (check security, then query a web service, then query the EF, etc.).

You could put that in the controller, but that's clearly wrong.

It should go in your service layer, of course. You might mock/fake out the service layer to test the controller, but now you need to test the service layer.

It would be nice if you could do this without connecting to a DB (or web service). And that's where Repository comes in.

The data service can use a "dumb" Repository as a source of data on which it can perform complex queries. You can then test the data service by replacing the repository with a fake implementation which uses a List<T> as its data store.

The only thing which makes this confusing is the large amount of examples that show controllers talking directly to repositories. (S#arp Architecture, I'm looking at you.) If you're looking at those examples, and you already have a service layer, then I agree that it makes it difficult to see what the benefit of the repository is. But if you just consider the testing of the service layer itself, and don't plan on having controllers talking directly to the repository, then it starts to make more sense.

Craig Stuntz