views:

168

answers:

5

Currently im using EF and using its datacontext directly in all of my actions, but since i started reading about loose coupling and testability im thinking that thats not the best way to go. Im trying to understand all the pro's and con's before i start refactor all my current code.

Problem 1: Considering that every entity needs its own repository, and thus has to setup its own connection to a datasource (lets assume a database using EF), wouldnt that give alot of overhead if i need data from 5 different entities on a single page?

Problem 2: What im seeing aswell in all the examples which i found online is that most people (even people like shanselman) implement the repository pattern using the entity classes which are generated by either LINQ or EF, doesn't this defeat the purpose of repository pattern with regards to loose coupling? On the other hand, what is the alternative, using POCO classes in combination with for example AutoMapper? (this scares me a little)

Im hoping that a few people can shed some light on this, because im a bit confused at the moment if the repository pattern is the right choice for a website.

+3  A: 

ObjectContext uses connection pooling, so it won't be as inefficient as you might think. Also, SQL servers (i.e. MSSQL) are really optimized for tons of concurrent connections.

As for how to implement it, I'd go with some IRepository interface. You can then make specific interfaces, i.e. PostRepository > IRepository, and finally, implement that in concrete classes (for example, a real class, and a fake in-memory one for testing).

Zor
Im aware of the fact that sql servers uses connection pooling, but my main concern is the way EF or LINQ maintains its context, there seems to be alot going on under water and that times 5 (or more) equals alot of overhead, or am i completely of base here?
Fabian
It was designed exactly to avoid such overhead. You can generally create a lot of ObjectContext objects in one go without any issues. But don't take it the wrong way; you shouldn't be careless.
Zor
EF/LINQ use ADO.NET under the hood, so they end up using the same connection pooling mechanisms.
Andrew Barber
+1  A: 

You can read this book. There is a good example of the using Repository pattern and LINQ.
Also there is this article Using Repository and Unit of Work patterns with Entity Framework 4.0.

Dublicator
Ive read that book a while ago, going to take another look at his examples
Fabian
That second link guided me most to what i finally implemented.
Fabian
+1  A: 

ADO.NET connection pooling will be managing the connections behind-the-scenes. It basically won't matter at all how many different entities (and therefore Repositories with their own context) you use; each DB operation will be taking connections from the same pool.

The reason for the repository is to enable you to abstract/replace the way the entities are being created for testing, etc. The entity objects can be instantiated like normal objects without the Context's services, so the test repo would do that for the test data

Andrew Barber
Additional note about connection pooling: This assumes that all connections are using the same connection string. Each individual connection string you may use (even if the only difference is an added space) gets its own pool of connection objects.
Andrew Barber
So it wont matter if i use a single datacontext or 10 if you look at performance?
Fabian
As far as the connections go, no measurable difference at all. All this also assumes no one has added a bunch of 'heavy' code to the datacontext or repositories.
Andrew Barber
Correct. The only thing would be GC overhead, but this is so insignificant that I probably shouldn't even be mentioning it.
Zor
Shouldn't be mentioning what? :P
Andrew Barber
Absolutely nothing!
Zor
+1  A: 

Firstly, I'm not aware of a requirement for each entity to have it's own repository so I'd junk that restriction.

For Scott H's implementation, I assume you are referring to the Nerd Dinner app, which by his own admission isn't really the repository pattern.

The objective of the repository pattern is, as you surmise, to isolate the data store from the layers above it. It's not purely for testing reasons, it also allows you to change the backing store without affecting your UI/Business Logic.

In purist terms you would create POCOs that you would return from the Repository to your BL, by using an interface to define the Repository contract you could then pass and use the interface rather than a concrete implementation. This would allow you to pass in any object that implemented the Repository interface, whether your live repository or a mocked repository.

In reality I use a repository with MVC with Linq to SQL as my backing store which allows me a degree of flexibility over the actual backing store so I use hand crafted L2S objects in my BL, these have additional fields and functionality that isn't persisted to the backing store. This way I get some great functionality from the L2S aspects, change tracking, object hierarchy, etc, while also allowing me to substitute a mocked repository for TDD.

Lazarus
I think im becoming one of those purists, is automapper the only way to instantiate if i want to prevent alot of left hand right hand coding? And hand crafted L2S objects intrigues me, thats like POCO but not really?
Fabian
You can use the automapper and then extend the classes (I believe EF like L2S creates partials) but EF carries a lot of other issues with it, I've not had need to use it as yet and know of at least one person who wants to dump it. Hand crafted L2S objects are effectively POCOs but decorated using Linq To SQL attributes and accessed through a data context instantiated by the repository.
Lazarus
+1  A: 

You hit the nail on the head in identifying the difficulty with using Entities as business objects. After much trial and error, here's the pattern that we've settled into, which has been working very well for us:

Our application is divided into modules, and each module is divided into three tiers: Web (front-end), Core (business), and Data. In our case, each of these tiers is given its own project, so there is a hard enforcement preventing our dependencies from becoming tightly-coupled.

The Core layer contains utility classes, POCOs, and repository interfaces.

The Web layer leverages these classes and interfaces to get the information it needs. For example, an MVC controller can take a particular repository interface as a constructor argument, so our IoC framework injects the correct implementation of that repository when the controller is created. The repository interface defines selector methods that return our POCO objects (also defined in the Core business layer).

The Data layer's entire responsibility is to implement the repository interfaces defined in the Core layer. It has an Entity Framework context that represents our data store, but rather than returning the Entities (which are technically "data" objects), it returns the POCOs defined in the Core layer (our "business" objects).

In order to reduce repetition, we have an abstract, generic EntityMapper class, which provides basic functionality for mapping Entities to POCOs. This makes the majority of our repository implementations extremely simple. For example:

public class EditLayoutChannelEntMapper : EntityMapper<Entity.LayoutChannel, EditLayoutChannel>,
    IEditLayoutChannelRepository
{
    protected override System.Linq.Expressions.Expression<Func<Entity.LayoutChannel, EditLayoutChannel>> Selector
    {
        get
        {
            return lc => new EditLayoutChannel
                             {
                                 LayoutChannelId = lc.LayoutChannelId,
                                 LayoutDisplayColumnId = lc.LayoutDisplayColId,
                                 ChannelKey = lc.PortalChannelKey,
                                 SortOrder = lc.Priority
                             };
        }
    }
    public EditLayoutChannel GetById(int layoutChannelId)
    {
        return SelectSingle(c => c.LayoutChannelId == layoutChannelId);
    }
}

Thanks to the methods implemented by the EntityMapper base class, the above repository implements the following interface:

public interface IEditLayoutChannelRepository
{
    EditLayoutChannel GetById(int layoutChannelId);
    void Update(EditLayoutChannel editLayoutChannel);
    int Insert(EditLayoutChannel editLayoutChannel);
    void Delete(EditLayoutChannel layoutChannel);
}

EntityMappers do very little in their constructors, so it's okay if a controller has multiple repository dependencies. Not only does the Entity Framework reuse connections, but the Entity Contexts themselves are only created when one of the repository methods gets called.

Each module also has a special Test project, which contains unit tests for the classes in these three tiers. We've even come up with a way to make our repositories and other data-access classes somewhat unit-testable. Now that we've got this basic infrastructure set up, adding functionality to our web application is generally pretty smooth and not too error-prone.

StriplingWarrior