Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modeling NHibernate queries

Usually I'd put my criterias/hql queries in a repository/dal class related to the entity, but lately I'be been thinking of adding another abstraction that represents what a query is, this would give me the possibility of adding common behavior to all queries (e.g. pagination) in a base class, etc.

so these are my components now;

generic interface not related to nhibernate:

public interface IQuery<T>
{
    IList<T> List();
    T Single();
}

Example implementation of a Criteria based query, something similar could be done with an Hql query, or a nhibernate-linq query

public abstract class CriteriaQuery<T>: IQuery<T>
{
    [Inject]
    public ISessionFactory SessionFactory { protected get; set; }

    protected ISession Session
    {
        get { return SessionFactory.GetCurrentSession(); }
    }

    protected abstract ICriteria Configure(ICriteria criteria);

    [Transaction]
    public virtual IList<T> List()
    {
        var criteria = Session.CreateCriteria(typeof (T));

        return Configure(criteria)
                 .List<T>();
    }

    [Transaction]
    public virtual T Single()
    {
        return Configure(Session.CreateCriteria(typeof(T)))
                .UniqueResult<T>();
    }
}

and here a domain specific query would look like:

public interface IGetVideosQuery: IQuery<Video>
{
    IGetVideosQuery Page(int index);
    IGetVideosQuery PageSize(int pageSize);

    IGetVideosQuery AllTime { get; }
    IGetVideosQuery Today { get; }
    IGetVideosQuery LastWeek { get; }
}

any thoughts on this? possible problems you see I might come across? Thanks!

like image 360
Sebastian Piu Avatar asked Oct 21 '10 20:10

Sebastian Piu


People also ask

Is NHibernate better than Entity Framework?

EF Core can use a ROWVERSION/TIMESTAMP column on SQL Server, or any of a list of columns, when updating a record. NHibernate offers richer capabilities, besides SQL Server ROWVERSION/TIMESTAMP, it can also use database native mechanisms such as Oracle's ORA_ROWSCN, but also timestamp or version columns.

What is fetch in NHibernate?

A fetching strategy is the strategy NHibernate will use for retrieving associated objects if the application needs to navigate the association. Fetch strategies may be declared in the O/R mapping metadata, or overridden by a particular HQL or Criteria query.

What is NHibernate in C#?

NHibernate is a mature, open source object-relational mapper for the . NET framework. It's actively developed, fully featured and used in thousands of successful projects. Easily map regular C# or VB.NET object models designed in Visual Studio.

What is lazy loading in NHibernate?

Any association, whether it be a many-to-one or a collection is lazy loaded by default, it requires an Open ISession. If you have closed your session, or if you have committed your transaction, you can get a lazy load exception that it cannot pull in those additional objects.


2 Answers

I took a different path, that of CQS. What this does is that it separates my mutating logic from my query logic.

Now, there are different ideas on how to implement this, and I choose this one:

  • All my mutation logic is activated using command like DeactivateUser and ChangeRelationAddress. For this business logic, I have normal repositories like you describe;

  • For displaying data, I use a completely managed system. With this system, I describe queries like the Specification Pattern. I describes the base table and the fields. The query system automatically creates the joins for me and with filter definitions I provide filters.

This system allows me to keep the complexity of my repositories down because I do not have to think about filters a user may set or ORDER BY's. The system that displays this data automatically creates the filters using Criteria and handles paging for me.

Maybe such a system can work for you.

like image 136
Pieter van Ginkel Avatar answered Oct 27 '22 10:10

Pieter van Ginkel


My first suggestion would be to go with Linq2NH, available in NHibernate 2.1 and beyond. The Session exposes an AsQueryable<T>() method on which you can build a Linq query. That will allow you to attach criteria and projections as you please using standard Linq extension methods, including Skip() and Take() to implement pagination (myQuery.Skip(PageIdx*PageSize).Take(PageSize).ToList()), and Where clauses to filter. The lambdas and variables used in those queries could be encapsulated in some sort of QueryInfo class, allowing repeatable, persistable queries.

like image 22
KeithS Avatar answered Oct 27 '22 11:10

KeithS