Command/Query separation when using an ORM

998 Views Asked by At

Within my various projects I implement the command/query separation pattern and use NHibernate as my ORM.

In general I keep my commands and queries in separate projects relevant to the particular set of activities such as UserManagement, TagManagement, QuestionManagement etc.

I quite like having everything divided up nicely into these repositories with easily findable functionality. There are certainly benefits in doing things this way.

I am however starting to wonder about the value of this abstraction for basic queries especially given that NHibernate already offers such a powerful abstraction by itself.

Consider this in my MVC controller:

_nHibernateSession.Get<UserProfile>(_sessionData.UserId);

I could abstract this out into a query in the UserManagement repository but I'm not sure what value that offers.

What do you think? Would you keep everything within the command/query paradigm or would you use the nhibernate session directly in your controllers for simple requests like this?

3

There are 3 best solutions below

0
On

I prefer to keep all queries in the repository, if you need to make a lot of different query you can expose the a repository that implements an IQueryable and wrap session.Query of LINQ To Nhibernate, that has limitations respect to HQL or Criteria.

But for me there isn't a valid reason to make this, only if you are providing a Data Access Layer to somebody else and you will not know the queries.

You can see an example of this on a DDD project I'm working.

0
On

I would strongly encourage you to maintain a level of abstraction between your MVC controller and NHibernate, especially if you need to do unit testing of your MVC controller. Without the repository layer, it is far more difficult to create Unit tests which require mocking of the repository layer.

0
On

Usually i'm not using repositories, because I think that they are adding too much abstraction into my code. I prefer View Model which is constructed directly in Service / Controller layer. If i want to write a unit test i can write it against service or controller. If you want to reuse some query criteria, then just write extension method:

    public static IQueryable<User> Administrators(this IQueryable<User> users)
    {
        return users.Where(x => x.Role.Id == Role.Const.Admin);
    }

Regarding this I recommend these articles: http://ayende.com/blog/3955/repository-is-the-new-singleton http://www.planetgeek.ch/2012/05/05/what-is-that-all-about-the-repository-anti-pattern/