Introducing NHibernate.FlowQuery

Hi all NHibernate users,

Today I finally decided to publish my very close-to-heart wrapper for the NHibernate ICriteria API. NHibernate.FlowQuery (FlowQuery) is based on expression trees and hence provides you with a refactoring friendly interface that can be completely free from “magic strings” even if you have mapped NHibernate to private or protected members in your entities.

FlowQuery provides you with an easy-to-use API for revealing hidden members by configurable conventions that can be altered on the fly. The API also contains auto-mapping functionality to map your query directly into a view-model instead of having you map it yourself.

Examples:

A simple get-all query:

var users = session.FlowQuery<User>().Select();

A simple get-all query which auto-maps public properties with the same name and type into the view-model:

var users = session.FlowQuery<User>().Select<UserViewModel>();

Restrictions:

var users = session.FlowQuery<User>()
    .Where(u => u.Firstname == "Niklas"
             && u.Lastname.StartsWith("K"))
    .Select();

The above query uses the method StartsWith which is part of the .NET String-class. FlowQuery converts this method-call to Restrictions.Like(“Lastname”, “K”, MatchMode.Start). The API also have support for Contains, EndsWith and, depending on database provider, Substring.

Joining:

UserRoleLink link = null;

var users = session.FlowQuery<User>()
    .Inner.Join(u => u.Roles, () => link)
    .Where(u => link.Role == Role.Administrator)
    .Select();

Selects only Id and Email into an anonymous type:

var users = session.FlowQuery<User>()
    .Select(u => new
    {
        u.Id,
        u.Email
    });

Selects only Id and Email but to the same type:

var users = session.FlowQuery<User>()
    .Select(u => u.Id, u => u.Email);

Selects only Firstname, Lastname and Email but by specifying type, constructor and member initializer:

var users = session.FlowQuery<User>()
    .Select(u => new UserViewModel(u.Firstname, u.Lastname)
    {
        Email = u.Email
    });

Revealing hidden members is done using either the Reveal-helper or by instantiating a custom revealer. The Reveal-helper, by default, uses the “m_”-convention.

As an example:

string name = Reveal.ByConvention(() => link.Role);

name would be “m_Role”.

The convention used by the Reveal-helper can be set using Reveal.SetConvention() which takes either a Func<string, string> or an IRevealConvention.

You can also use a custom revealer like:

IRevealer revealer = new Revealer(new UnderscoreConvention());
string name = revealer.Reveal(() => link.Role);

name would be “_Role”.

Revealing in a query:

var users = session.FlowQuery<User>()
    .Inner.Join(Reveal.ByConvention<User>(u => u.Roles), () => link)
    .Where(u => link.Role == Role.Administrator)
    .Select();

The above query reveals the hidden collection m_Roles and joins it into the query.

I think those examples will be sufficient for now. If you like what you see and/or want more information about FlowQuery leave a reply!

The API can be downloaded as a dll at: http://sourceforge.net/projects/nhflowquery/

Enjoy! (:

/Niklas Källander