Does Nhibernate CommitAsync wait for all Async CRUD Operations?

Viewed 253

I'm trying to figure out how the CommitAsync method in nhibernate works in conjunction with SaveAsync, UpdateAsync, & DeleteAsync

My question is: say i call SaveAsync, or UpdateAsync multiple times without awaiting them. Then sometime later I call CommitAsync. Will CommitAsync wait for all of the calls to SaveAsync and UpdateAsync to finish? Or do i have to await them before calling CommitAsync?

I Created the test below and tried saving multiple users without awaiting them then tried to commit using CommitAsync to see if any would be missing from the DB or if the count would be off but it seems to work. However, every example I've seen online awaits all of their async CRUD operations before committing.

[TestFixture]
public class AsyncTests
{
    [Test]
    public async Task TestAsync()
    {
        var sessionSource = new SessionSource();
        int saveCount = 100000;
        using (var session = sessionSource.CreateSession())
        {
            using (var t = session.BeginTransaction())
            {
                SaveMany(saveCount, session);
                await t.CommitAsync();
            }
        }

        int count = 0;
        using (var sessoin = sessionSource.CreateSession())
        {
            count = sessoin.Query<User>().Count();
        }

        Assert.That(count, Is.EqualTo(saveCount));
    }

    public void SaveMany(int count, ISession session)
    {
        for (var i = 0; i < count; i++)
        {
            Save(session);
        }
    }

    private Task<object> Save(ISession session)
    {
        return session.SaveAsync(new User()
        {
            Guid = Guid.NewGuid(),
            FirstName = "saveasync",
            MiddleName = "middle",
            LastName = "last"
        });
    }
}
1 Answers

Based on this article: NHibernate 5: async IO bound operations support
you should await all of the async methods.

Here I copy the relevant part:
Note that this feature is not intended for parallelism, only non-parallel asynchrony, so make sure to await each call before issuing a new call using the same session.

In other words, don’t do this:

Task<Customer> task1 = session.GetAsync<Customer>(1);
Task<Customer> task2 = session.GetAsync<Customer>(2);

Customer[] customers = await Task.WhenAll(task1, task2);

Do this instead:

Customer customer1 = await session.GetAsync<Customer>(1);
Customer customer2 = await session.GetAsync<Customer>(2);

A quick side note about parallelism versus asynchrony. Parallel execution is a subset of asynchronous execution: every parallel execution is asynchronous, but not every asynchronous execution is parallel.

Executing something asynchronously corresponds to "without blocking the caller". It can be achieved by starting this work immediately, which means it will be done in parallel, or by waiting until the caller is finished with their stuff, which means the work will be executed sequentially, either by the same or another thread. Either way, the job will not block the caller and thus we can say that it will be executed asynchronously.

Related