Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate query strategies in web applications

In web application scenarios, there are commonly two requirements regarding data retrieval: 1. All queries need to be paged optionally 2. There are alot of "filtering" queries needed by the user (e.g. search Person by name AND mail AND age) 3. Sorting queries implied by some clientside grid

And of course the combined case: Filtered, paged queries which are sorted :)

These requirements can lead to alot of repository methods in the data layer, each with alot of parameters. Are there any common patterns of giving this process a more dynamic behavior (e.g. auto-generated queries depending on domain class properties)?

I'm aware of the fact that repository methods should be clean and well-defined. But at the moment, I feel like writing alot of boilerplate code whenever I add some filtering form to an MVC-view or some sortable paged table.

How do other developers handle such requirements?

Thank you in advance

like image 822
mbue Avatar asked Mar 22 '12 10:03

mbue


2 Answers

Repositories, generic repositories and repositories that expose IQueryable is a much heated debate.

The bottom line is a repository that is generic or exposes IQueryable is not a a real repository at all, it is merely an abstraction of your data layer.

Now this is not a bad thing to have but don't call it a repository, call it what it is. A data layer abstraction allows you to quickly insert something into your UI where you read and write entities without leaking your data layer framework into the UI. You could of course just inject an ISession and be done with it.

public interface IRepository<T> {}

public class NHibernateRepository<T> : IRepository<T>
{
    private ISession session;

    public NHibernateRepository(ISession session)
    {
        this.session = session;
    }

    T Get(object id) { return session.GetById<T>(id)); }

    IQueryable<T> Query { get { return session.Query<T>(); }
}

new NHibernateRepository<Customer>(session).Query().Where(customer => customer.Name == Fred);

However if you want to capture some reusable logic and provide a clear contract between your services or UI and your data layer then a Repository does just that. You define clear methods that says what it is retrieving and how. Additionally with a repository you only want to expose your aggregate roots, these are the root entities to which all your other data hangs off, these could be things like Customer and Supplier. You wouldn't try to get to an address directly you would load up a customer and then query his addresses. You would load a list of suppliers based on what things they supply but you wouldn't go via a 'ItemsRepository'. My examples may not be the best but they give you an idea.

public class CustomerRepository
{
    public Customer GetCustomerWithName(string name);
}

public class SupplierRepository
{
    public IEnumerable<Supplier> GetSuppliersWhoStockItem(string itemName)
}

Finally if your adventurous you might want to look at CQRS, it is to big of a subject to outline here but there are plenty of examples.

The first is quicker to implement, the second gives you clearer reusable code, the third gives you a separation between your UI layer but requires more ground work. It depends on what you need and want and should probably be tackled in that order.

like image 189
Bronumski Avatar answered Oct 20 '22 14:10

Bronumski


In our project we've used repositories too, repository per entity, but I don't enjoy about it. It can do a lot of problem when you write complex queries with a lot of interact entities. I think it'll be a one generic repository for base operations, and all queries should be present with Query Object pattern, something like separate class per query, although look at:

http://richarddingwall.name/2010/06/15/brownfield-cqrs-part-1-commands/

http://codebetter.com/gregyoung/2009/01/20/ddd-specification-or-query-object/

http://devlicio.us/blogs/casey/archive/2009/02/13/ddd-command-query-separation-as-an-architectural-concept.aspx

http://blog.jonathanoliver.com/2009/10/dddd-why-i-love-cqrs/

http://www.udidahan.com/2007/03/28/query-objects-vs-methods-on-a-repository/

like image 3
Anton Avatar answered Oct 20 '22 13:10

Anton