56

NHibernate on ASP.NET Core

 5 years ago
source link: https://www.tuicool.com/articles/hit/jiMZNz2
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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.

AvI7Nbr.png!web

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.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK