NHibernate on ASP.NET Core

NHibernate has been my favorite ORM for long time. Although it’s more complex for beginners than Entity Framework it’s more matured and many developers consider it to be practially an industry standard. NHibernate works with ASP.NET Core too. This blog post shows how to use NHibernate in ASP.NET Core MVC applications.

I was pleasantly suprised seeing that NHibernate is now on .NET Standard and it doesn’t come with any secret dependencies to full .NET Framework or some Windows-only library. I mean I can take ASP.NET Core project that uses NHibernate and just deploy it to Linux server. Bam! It works!

Getting started

First I created default ASP.NET Core application on Visual Studio and then added these two NuGet packages:

And then, my dear friends, I started with architectureless code to find out if it really-really works. With fast copy and paste I organized connection string to appsettings.json, created simple database to test machine and wrote the following piece of initialization code.

var connStr = Configuration.GetConnectionString("DefaultConnection");
_sessionFactory = Fluently.Configure()
                          .Database(MsSqlConfiguration.MsSql2012.ConnectionString(connStr))
                          .Mappings(m => m.FluentMappings.AddFromAssembly(GetType().Assembly))
                          .BuildSessionFactory();
           
services.AddScoped(factory =>
{
    return _sessionFactory.OpenSession();
});

As I didn’t bother to mess with mapping XML-s I went with FluentNHibernate and defined mappings (okay, just one mapping) in code.

public class BookMap : ClassMap<Book>
{
    public BookMap()
    {
        Id(b => b.Id);
        Map(b => b.Title);
        Table("Books");
    }
}

With this bold configuration under belt I wrote sample controller. Yes, I skipped data layer like lazy men skip foreplay. I also added simple query to list all books in my database table.

public class HomeController : Controller
{
    private readonly ISession _session;

    public HomeController(ISession session)
    {
        _session = session;
    }

    public IActionResult Index()
    {
        var list = _session.Query<Book>().ToList();
           
        return View();
    }

    public IActionResult Error()
    {
        var requestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
        return View(new ErrorViewModel { RequestId = requestId });
    }
}

I added breakpoint to return statement in Index() action and ran my application. Yep, it hits the breakpoint and data gets loaded with no single problem.

Async mehtods

Although it has been around some time I want to bring out important thing – async methods in NHibernate. Yes, NHibernate is on same train with Entity Framework and it supports all kind of async operations.

public async Task<IActionResult> Index()
{
    var list = await _session.Query<Book>().ToListAsync();
    var book = await _session.GetAsync<Book>(1);

    using (var transaction = _session.BeginTransaction())
    {
        book.Title += " (sold out)";

        await _session.SaveOrUpdateAsync(book);
        await transaction.CommitAsync();
    }

    return View();
}

This is nice because support for async is well implemented in ASP.NET Core. Classic MVC had issues with it. Some things supported async and others not very well. On ASP.NET Core we can write the code we like and framework carries out its duties as expected.

NHibernate LINQ

Another nice thing that has grown over years and got better is LINQ support in NHibernate. Yes, we can use LINQ on NHibernate queries and in big part it looks similar to what we have seen with Entity Framework.

public async Task<IActionResult> Index()
{
    var books = await _session.Query<Book>()
                              .Where(b => b.Title.StartsWith("B"))
                              .Skip(1)
                              .Take(2)
                              .ToListAsync();
    return View();
}

Let’s try out what happens if I set up multiple where-clause trap on what Entity Framework badly failed generating me the ugliest SQL of century.

public async Task<IActionResult> Index()
{
    var books = await _session.Query<Book>()
                              .Where(b => b.Title.StartsWith("B"))
                              .Where(b => b.Title.Length >= 5)
                              .Skip(1)
                              .Take(2)
                              .ToListAsync();
    return View();
}

Notice here two where-clauses at row. This is shortcut to common scenario where conditions are added to query dynamically based on given values. Want to scare yourself? Although different story but similar mess. Take a look at blog post What happens behind the scenes: NHibernate, Linq to SQL, Entity Framework scenario analysis by Oren Eini.

NHibernate has been far ahead of even Entity Framework 6 for years. We have to do something really stupid to mess things up in NHibernate to get such an ugly queries. This is how NHibernate solves the problem – just read between the lines literally.

NHibernate query translated to SQL

It’s minimal, nice and clean. No sub-select per where clause in LINQ expression tree. So, on .NET Core NHibernate still works the way it worked before and we don’t have to be afraid going with it.

Wrapping up

NHibernate has my warm welcome to .NET Core platform. It was and still is a leading ORM and stable work horse behind many complex data access layers in world. Over years NHibernate is modernized supporting now async calls and LINQ queries. It still remains kind of complex for beginners but with help of FluentNHibernate it will be easier to get started. Anyway I’m sure my next ASP.NET Core projects will go on NHibernate.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    7 thoughts on “NHibernate on ASP.NET Core

    • February 27, 2019 at 4:48 pm
      Permalink

      You dont need Fluent Nhibernate anymore, mapping by code is built in now.

    • February 28, 2019 at 11:39 pm
      Permalink

      Good to know. Thinking about switching… Tx!

    • March 29, 2019 at 7:47 pm
      Permalink

      Hi Gunnar, I’m new to NHibernate. Do you recommend any sources to start with? A book, a course …

    • April 1, 2019 at 6:51 am
      Permalink

      Hi, Fabricio. I learnt NHibernate by experimenting and what I found from internet. They have online documentation available and there are also many tutorials, articles and blog posts in internet that help you when getting started.

    • May 14, 2019 at 10:33 am
      Permalink

      People shoule be aware that Fluent NHibernate is absolete and that this is a good example on how not to do.

    • May 23, 2019 at 9:37 am
      Permalink

      Please forget FluentNhibernate, consider conformist API, It’s a modern way to map entities, then it’s integrated into nhibernate framework, you don’t have to add other dependencies like FluentNhibernate or others.

    • August 21, 2019 at 5:48 pm
      Permalink

      .Mappings(m => m.FluentMappings.AddFromAssembly(GetType().Assembly)) which kind of mapping should I use to map all my classesmap ?? Could you explain please?

    Leave a Reply

    Your email address will not be published. Required fields are marked *