6

Given this code:

private ISession _session;

public async Task<T> GetAsync<T>(int id) where T : ISomeEntity
{
    //how to call and return _session.Get<T>(id) asynchronous
}

Is it possible to call NHibernate ISession.Get<T>() asynchronously? Advisable? Not worth it?

i3arnon
  • 113,022
  • 33
  • 324
  • 344
mxmissile
  • 11,464
  • 3
  • 53
  • 79
  • 2
    NHibernate does support async operations now: http://enterprisecraftsmanship.com/2017/12/11/nhibernate-async-support/ – Vladimir Dec 18 '17 at 12:15

3 Answers3

14

NHibernate does not support Async await in the sense of entity framework does by default. However it would be recommended to do so (if you could) since a database call is an IO call which is a very good candidate to make it async. As a result while waiting response from DB your thread will return to the pool instead of being pend and it will make your app more scalable. Now coming to async support. I have forked NHibernate to achive this. In my fork which I call NHibernateX, there are Async Methods like GetAsync, ListAsync, ToListAsync etc Here's the source and nuget package:

https://github.com/ReverseBlade/nhibernate-core

https://www.nuget.org/packages/NHibernateX/

Onur Gumus
  • 1,389
  • 11
  • 27
  • 1
    Hi, I have pulled down the NHibernateX library and was looking through it. I was wondering if you happen to have any examples to share so I may be able to get some better ideas on how to put this to use. Thanks! – MattB Dec 19 '16 at 14:42
  • 1
    @MattB see this API changes, https://github.com/OnurGumus/nhibernate-core/commit/ef67c54724c24ce44915805331dd4af25917f15a – Onur Gumus Dec 20 '16 at 06:06
  • for what it's worth, NHibernate now supports async / await (since 2017): https://enterprisecraftsmanship.com/posts/nhibernate-async-support/ – zcrar70 Sep 26 '19 at 21:51
8

If the underlying operation ins't already asynchronous in some way (i.e. async-await, BeginXXX/EndXXX, etc.) there's no value in adding an async wrapper around it.

async is useful in 2 cases: scalability and responsiveness. Doing async over sync doesn't help with scalability at all and for responsiveness you can simply use Task.Run to offload that work to another ThreadPool thread when you need instead of adding a dedicated method.

More in Should I expose asynchronous wrappers for synchronous methods?

i3arnon
  • 113,022
  • 33
  • 324
  • 344
  • Even Async Await would offload the execution to a thread pool, isn't that a better mechanism than using Task, which offloads from the beginning of the method. In this case it can be synchronous till it doesn't take much time and aynchronous from the point await is used – Mrinal Kamboj May 09 '15 at 01:48
  • @MrinalKamboj async-await doesn't offload to the `ThreadPool`. All the `async` keyword does is let you use `await` inside the method, and there's nothing to `await` here. – i3arnon May 09 '15 at 01:52
  • On using await in a method marked with async, aren't we off the context of main thread / calling thread, then it has to be a separate thread. In fact return for Async methods is mostly Task. Interesting part is post await it switches back to the context of main / calling thread like UI – Mrinal Kamboj May 09 '15 at 01:56
  • @MrinalKamboj Before the first `await` the execution is on the calling thread. After the `await` you're usually either on a `ThreadPool` thread or the UI thread. What matters is what happens between. While a (truly) `async` operations is being executed there is no thread at all. Here however, there's no task to `await`. You can create one with `Task.Run` but that would be blocking a `ThreadPool` thread throughout the entire operation. – i3arnon May 09 '15 at 02:00
  • Async is better than just Task.Run for responsiveness because it can marshal code back onto the UI thread later with explicitly having to write .NET 4.0 style continuations. Though of course you can `await` the results of `Task.Run` when appropriate. – Jonathan Allen Oct 29 '16 at 09:40
  • @JonathanAllen `async` here means an async wrapper, which there's no reason to add. Of course if you use `Task.Run` directly from UI code you can await it if that makes sense. – i3arnon Nov 06 '16 at 08:31
6

NHibernate 5 now support the pattern

private ISession _session;

public async Task<T> GetAsync<T>(int id) where T : ISomeEntity
{
    return await _session.GetAsync<T>(id);
}
Soma Mbadiwe
  • 1,594
  • 16
  • 15