The repository anti pattern clarified

In my last post I showed the transformation from the generic repository to the unit of work pattern only. I received an interesting question in the comment section.

Looks nice so far. But didn’t you mix up and simplify things a little bit too much here? For me the Repository is the separation of Domain Objects and Persistent Entities. It’s also a separation of the client from the used persistency technology (either NHibernate, EF, SharePoint, ADO.NET, WebService or whatever). As client side calling code, I really don’t care, where and how my data is stored.

Of course the interface of the repository should be expressive enough and not generic as this was mentioned many times by you and the different contributors.

But why do you mix together the Repository with the UnitOfWork and the transaction handling? Is it something NHibernate specific? Did I miss your point?

I want to clarify my point in this blog post.

I don’t think I mixed up a little too much. The implementation I show in the blog post is moving from the repository pattern to the unit of work pattern. The article shows that a repository is an unneccesary abstraction which can be removed. Let us look into the formal definition of repositories and unit of work:

“A REPOSITORY represents all objects of a certain type as a conceptual set (usually emulated). It acts like a collection, except with more elaborate querying capability. Objects of the appropriate type are added and removed, and the machinery behind the REPOSITORY inserts them or deletes them from the database. This definition gathers a cohesive set of responsibilities for providing access to the roots of AGGREGATES from early life cycle through the end.”
[…] “Although the REPOSITORY will insert into and delete from the database, it will ordinarily not commit anything. It is tempting to commit after saving, for example, but the client presumably has the context to correctly initiate and commit units of work. Transaction management will be simpler if the REPOSITORY keeps its hands off.”
– Domain Driven Design: Tackling complexity in the heart of the software –

and the unit of work

“When you’re pulling data in and out of a database, it’s important to keep track of what you’ve changed; otherwise, that data won’t be written back into the database. Similarly you have to insert new objects you create and remove any objects you delete.”
[…] “A Unit of Work keeps track of everything you do during a business transaction that can affect the database. When you’re done, it figures out everything that needs to be done to alter the database as a result of your work.”
– Patterns of Enterprise Application Architecture –

As we see the two definitions closely relate to each other. The repository does not only offer querying capabilities but also allows to add and remove entities. But Repositories itself should not commit operations on the database. That is the responsibility of the unit of work. But the unit of work itself has to keep track of changes (add, removes and updates). Even querying requires the usage of an explicit business transaction (aka unit of work scope), not having an explicit transaction can result in implicit (and autocommiting transactions, see (1)). Therefore for querying we should also wrap these in a unit of work scope. I always prefer being explicit about my unit of work boundaries.

So what I did in the end is: I moved the add, remove and update responsibility solely to the unit of work (as it has to keep track of changes anyway). When you do that all what is left on the repository is the querying capability. Querying also needs explicit unit of work boundaries (business scope) and this can also be moved to the unit of work. Hope that helps.

(1)
NHibernate: “When we don’t define our own transactions, it falls back into implicit transaction mode, where every statement to the database runs in its own transaction, resulting in a large performance cost (database time to build and tear down transactions), and reduced consistency.”
http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions
EF: “When performing a SaveChanges operation, the Entity Framework implicitly wraps all of the commands in a database transaction; however, you can take control of transactions as well.”
http://msdn.microsoft.com/en-us/library/orm-9780596520281-01-16.aspx

About the author

Daniel Marbach

2 comments

  • I am a supporter of CQRS and thus I use different repositories for writes and reads (the only query in a ‘write’ repository is Get(entityId) ). This means the query repository doesn’t need to know about UoW, transactions etc. For a bounded context you can have a specific repo (as an abstraction, the implementation can be one class to rule’em all) that handles only those needs. And since it’s a query this means no updates thus no need for Uow or transacations, AR etc. A simple model (which will be a part of the View Model) will be returned.

    I do consider that a repository can commit. Yes it might be part of another transaction so you’d have nested transactions, but in the end the Repo can call ‘transaction.Commit()’ and let the transaction decide if it’s a ‘real’ commit or only decrease of the nested level. The repo acts as a manager of persistence objects. This means it gets injected the DAO, ISession etc but it doesn’t control their lifetime (the DI Container manages their scope and lifetime).

    I usually stay away from the big ORMs and use a micro-Orm like PetaPoco (it has though its part of headaches). Of course, using the REpository pattern this detail doesn’t matter for the rest of the app, I should be able to change any ORM with other. It does matter when implementing the repo and I found that transactions work very well.

    Yes, most of the time are implicit transactions but to make it an explicit one I need only to decorate my controller action with the TransactionalAttribute which simply starts a transaction before action executes and commits it afterwards. The same transaction is shared by the repo via DI Container magic, so the repo can do its job without caring about this bit. When needed, it will just call ‘StartTransaction’ and the DAO is smart enough to know that an already started transaction just got a level more deep.

    In the end it depends on how the objects are designed to work together. With the setup from above, everything that needs to be decoupled is decoupled and it’s cohesive. If for an operation I don’t care about explicit transactions the repo handles it for me. If for others I need explicit outside the repo transaction, I can do it as well, the repo allows me to do that. It does everything is supposed to in a flexibile way.

Recent Posts