0

A bit context at first: it's a web application, specifically this one running self hosted via nancy on mono, but web application as context should be already enough. The ORM is ServiceStack's OrmLite and DB is postgres (but I think question+answer will apply to other ORMs and DBs as well).

Imagine having code like this:

using (var transaction = Context.OpenTransaction())
{
    Context.InsertAll<T1>(t1Data);
    Context.InsertAll<T2>(t2Data);
    Context.InsertAll<T3>(t3Data);
    Context.InsertAll<T4>(t4Data);

    transaction.Commit();
}

I'm opening a transaction and need to insert different data into different tables. Of course I need all or none data to be inserted. Now one could be too clever and use async methods in order to do it faster:

using (var transaction = Context.OpenTransaction())
{
    var t1 = Context.InsertAllAsync<T1>(t1Data);
    var t2 = Context.InsertAllAsync<T2>(t2Data);
    var t3 = Context.InsertAllAsync<T3>(t3Data);
    var t4 = Context.InsertAllAsync<T4>(t4Data);

    await Task.WhenAll(t1, t2, t3, t4);

    transaction.Commit();
}

To the best of my knowledge, this won't work. It won't work for sure, if the different tables reference each other, but even if they won't, database connections aren't thread safe and opening new connections for each insert wouldn't be the same, as one would need a distributed transaction (and again, references don't work). So, bad idea. But what about this:

using (var transaction = Context.OpenTransaction())
{
    await Context.InsertAllAsync<T1>(t1Data);
    await Context.InsertAllAsync<T2>(t2Data);
    await Context.InsertAllAsync<T3>(t3Data);
    await Context.InsertAllAsync<T4>(t4Data);

    transaction.Commit();
}

If I understand nodeJS correctly, than it's single threaded and you basically need to use the equivalent of the 3rd option, otherwise your whole application will be stuck and unusable.

However, .Net and Mono are multithreaded. For me the ...Async functions always seemed like a fluffy way to hide background threads. In that case there wouldn't be any real difference between 1 and 3, except that 1 is a bit faster (no additional background threads) and simpler to read.

But is this correct? Or would it depend on the ORM, whether the asyc-functions are truly asynchronous and don't just start background threads. Because if the same thread can handle other tasks in the meanwhile (such as in nodejs) than the 3rd option should have advantages for scalability.

I didn't write any pseudo benchmarks on purpose, as I doubt I'd get the benchmark right and the answer about the architecture of .net (and mono) should make obvious, if it makes sense to immediately await async calls or not.

peter
  • 14,348
  • 9
  • 62
  • 96
  • I would say yes, according to an answer by someone last time on an entirely different topic, that happened to include async operations... but it's better if you see what others think. – Kaitlyn Sep 03 '15 at 15:20
  • _"Async functions always seemed like a fluffy way to hide background threads"_ - not always. They're particularly good where you're waiting on high latent I/O operations such as disk, network and database and do so rather efficiently without creating explicit threads. See I/O completion ports. –  Sep 03 '15 at 15:22
  • I wouldn't expect async io bound operations to start background threads so the difference between 1 and 3 is that 3 will not block the asp.net thread – Ben Robinson Sep 03 '15 at 15:24
  • @MickyDuncan - that might be. I mostly got in contact with them through SOAP clients (which later became WCF). If I recall correctly, I've seen some `...Async` functions just executing the sync functions in a background thread. And since than whenever somebody mentioned async, I had that in mind. – peter Sep 03 '15 at 15:25
  • 2
    Linked [duplicate](http://stackoverflow.com/questions/9453560/why-use-async-requests-instead-of-using-a-larger-threadpool) is one of many "why use async" questions - with resounding "use for Web Sites/services to improve scalability". I think it covers your question pretty well, if not - consider searching for similar posts first (add [Stephen Cleary](http://stackoverflow.com/users/263693/stephen-cleary) to search queries to improve results). – Alexei Levenkov Sep 03 '15 at 15:25
  • @peter if library you are using does not implement asynchronous methods correctly (i.e. using busy wait in some form or any other approach to not release threads on long I/O bound operations) it would be very different answer - duplicate applies for honest implementation of async operations. If not the case - please update the post so it is clear that you need another answer/duplicate. – Alexei Levenkov Sep 03 '15 at 15:28
  • @AlexeiLevenkov thx for the reference. I just found out that although ormlite supports async, npgsql doesn't have full async support just yet and therefore ormlite's dialect provider for postgres doesn't support async either. - But I'll go on github with that specific question, as a general question + reference it was very helpful – peter Sep 03 '15 at 15:38

0 Answers0