18

I'm starting a new project and have decided to try to incorporate DDD patterns and also include Linq to Entities. When I look at the EF's ObjectContext it seems to be performing the functions of both Repository and Unit of Work patterns:

Repository in the sense that the underlying data level interface is abstracted from the entity representation and I can request and save data through the ObjectContext.

Unit Of Work in the sense that I can write all my inserts/updates to the objectContext and execute them all in one shot when I do a SaveChanges().

It seems redundant to put another layer of these patterns on top of the EF ObjectContext? It also seems that the Model classes can be incorporated directly on top of the EF generated entities using 'partial class'.

I'm new at DDD so please let me know if I'm missing something here.

Weej
  • 1,012
  • 2
  • 8
  • 24

3 Answers3

17

I don't think that the Entity Framework is a good implementation of Repository, because:

  • The object context is insufficiently abstract to do good unit testing of things which reference it, since it is bound to the DB access. Having an IRepository reference instead works much better for creating unit tests.
  • When a client has access to the ObjectContext, the client can do pretty much anything it cares to. The only real control you have over this at all is to make certain types or properties private. It is hard to implement good data security this way.
  • On a non-trivial model, the ObjectContext is insufficiently abstract. You may, for example, have both tables and stored procedures mapped to the same entity type. You don't really want the client to have to distinguish between the two mappings.
  • On a related note, it is difficult to write comprehensive and well-enforce business rules and entity code. Indeed, whether or not it this is even a good idea is debatable.

On the other hand, once you have an ObjectContext, implementing the Repository pattern is trivial. Indeed, for cases that are not particularly complex, the Repository is something of a wrapper around the ObjectContext and the Entity types.

Craig Stuntz
  • 125,891
  • 12
  • 252
  • 273
  • 2
    Thanks Craig. I came across some code in a blog by Simon Segal at http://www.simonsegal.net/blog/2009/01/13/entity-framework-repository-specifications-and-fetching-strategies/ that provides some sample Repository implementation for Entity Framework. – Weej Feb 06 '09 at 15:03
  • Are you currently using EntityFramework in your designs? Is there any difficulty in the implementation? Thanks again – Weej Feb 06 '09 at 15:06
  • Yes, we are using the Entity Framework. There is no difficulty at all in implementing Repository around; is trivial. We have all kinds of difficulties with the Entity Framework itself; I think this is probably true for any ORM. – Craig Stuntz Feb 06 '09 at 15:48
7

I would say that you should look at the ObjectContext as your UnitOfWork, and not as a repository.

An ObjectContext cannot be a repository -imho- since it is 'to generic'. You should create your own Repositories, which have specialized methods (like GetCustomersWithGoldStatus for instance) next to the regular CRUD methods.

So, what I would do, is create repositories (one for each aggregate-root), and let those repositories use the ObjectContext.

Frederik Gheysels
  • 56,135
  • 11
  • 101
  • 154
  • Thanks for the comments Frederik. Would you implement GetCustomersWithGoldStatus directly in the repository? Have you considered using Extension methods? Do you think Extension methods have a place in this scenario? – Weej Feb 06 '09 at 15:10
  • On which type would you create such an extension method ? I would indeed create it on the repository, but not as an extension method. The repository can be regarded as 'the collection' where you get entities from, so I think it is a valid place to do it in this way – Frederik Gheysels Feb 06 '09 at 15:12
0

I like to have a repository layer for the following reasons:

EF gotcha's

When you look at some of the current tutorials on EF (Code First version), it is apparent there's a number of gotcha's to be handled, particularly around object graphs (entities containing entities) and disconnected scenarios. I think a repository layer is great for wrapping these up in one place.

A clear picture of data access mechanisms

A repository gives a specific picture as to how the BL is accessing and updating the data store. It exposes methods that have a clear single purpose, and can be tested independently of the BL. Standard example from the textbooks, Find() to find a single entity. A more application specific example, Clear() to clear down a db table.

A place for optimizations

Inevitably you come up against performance hits when using vanilla EF. I use the repository to hide the optimization mechanisms from the BL.

Examples,

GetKeys() to project cached keys from the tables (for Insert/Update decisions). The reading of key only is faster and uses less memory than reading the full entity.

Bulk load via SqlBulkCopy. EF will insert by individual SQL statements. If you want a single statement to insert multiple rows, SqlBulkCopy is a good mechanism. The repository encapsulates this and provides metadata for SqlBulkCopy. As well as the Insert method, you need a StartBatch() and EndBatch() method, which is also an argument for a UnitOfWork layer.

Ackroydd
  • 1,482
  • 1
  • 13
  • 14