0

Is await database.SaveChangesAsync() functionally equivalent to database.SaveChanges() ? If so, are there any benefits in using the async version if I need to update the database immediately ? Are there even more overheads in doing that ?

Thanks !

Update: I'm updating the question to give a better picture of my use case. This is in response to an answer below.
I'm writing WebAPI calling a Mediatr. I'm doing CRUD type of transaction. And I really needed to update the database and then continue from there. I don't see a need to spawn off a (what I saw on YouTube video) state machine to process the database update. Am I thinking correctly ? So if that's the case, I really don't need to do a await database.SaveChangesAsync, right ? I should just do a database.SaveChanges() and let the database update happen in the current thread. That's the purpose of my question. Is this thinking correct ?

EBDS
  • 1,244
  • 5
  • 16
  • Does this answer your question? [Understanding async / await in C#](https://stackoverflow.com/questions/14177891/understanding-async-await-in-c-sharp) – Progman Dec 19 '22 at 01:28
  • @Progman No. I believe I understand async / await. I've updated the question to give a use case of my scenario. What I asking is if I really want to wait for the database to update before continuing, I shouldn't be using await database.SaveChangesAsync(), right ? And there is then no reason to use "await database.SaveChangesAsync()" (ie immediately await async()" at all cause it only cause extra overheads. I should just use database.SaveChanges() and that's it if I want to immediately update and wait before I continue. – EBDS Dec 19 '22 at 13:31
  • Settling the Biggest Await Async Debate in .NET https://youtu.be/aaC16Fv2zes – EBDS Dec 23 '22 at 08:44

1 Answers1

2

Lots of codebases provide async and sync methods. The difference is the sync method will lock your thread. Essentially when you call the 'await database.SaveChangesAsync()' method, the tasks sets up an event to resume processing when you get a result and the thread returns to the pool. Performance wise, for large systems the more you make use of async/await the lower the drain on system resources.

Using async await also lets you do things like this

private async Task Foo() {
    var dataBaseResultTask = database.SaveChangesAsync();
    SomeOtherWorkICanDoWithoutWaiting();
    await dataBaseResultTask;
}

In general, if you can use the async version of a method, you should. But if you're calling the database from a sync method, it's not the end of the world to use the sync variant. They are functionally the same. Generally though, the more you use C# the more async will spread through your system like a virus, eventually you're gonna have to give in.

Updating for updated question:

In an API context, crud operations make a lot of sense to use the async variant. Say you have 10 requests coming in at slightly different times, the 10 method calls will reach the database step, freeze the thread and wait for the database to respond. You now have 10 threads locked up despite your API not actually doing any processing. On the other hand if all the methods do await databaseAsync, all 10 threads will spin up, trigger the database call, and then return to the pool freeing them up for other API calls/processes. Then when replies from the database come back whatever threads are available will spin up, process the replies and then return to the pool again.

For a small API you can get away with either method but best practices wise, your use case is textbook for async await. Tl;dr; The method itself will behave the same with either approach, but use less resources with async await.

The Lemon
  • 1,211
  • 15
  • 26
  • "the thread returns to the pool." - no, the thread returns to the pool at the point of await assuming the task is not resolved immediately – Crowcoder Dec 19 '22 at 01:56
  • English is a wonderfully vague language, that is what I meant. To be completely technical it only returns the thread once a truly async process is started. If SaveChangesAsync() was a synchronous method in an async overcoat, the await decorator would do literally nothing. For OP - if you want to treat sync code as async, stick it in a Task.Run(DoWork) wrapper – The Lemon Dec 19 '22 at 02:07
  • @TheLemon I'm writing WebAPI calling a Mediatr. I'm doing CRUD type of transaction. And I really needed to update the database and then continue from there. I don't see a need to spawn off a (what I saw on YouTube video) state machine to process the database update. Am I thinking correctly ? So if that's the case, I really don't need to do a await database.SaveChangesAsync, right ? I should just do a database.SaveChanges() and let the database update happen in the current thread. That's the purpose of my question. Is this thinking correct ? – EBDS Dec 19 '22 at 13:23
  • @Crowcoder My understanding is that the thread before and after the await are different. Is that what you mean ? – EBDS Dec 19 '22 at 13:32
  • @EBDS no. The thread will be the same in a context-aware environment if you do not use ConfigureAwait(false). It may or may not be the same if you do. Give [this a read](https://devblogs.microsoft.com/dotnet/configureawait-faq/) – Crowcoder Dec 19 '22 at 14:07
  • @EBDS updated the answer, but basically I strongly recommend async await for your use case, API Endpoints are normally pretty simple to asyncify too – The Lemon Dec 20 '22 at 21:17
  • @TheLemon I thought NOT using await in this case would use less resources ? It would then be running in my current thread and since I'm not doing something concurrently, I just let my thread do the database update. If I await, I will run the database update in another thread which would incur additional resources ? – EBDS Dec 21 '22 at 02:46
  • to create an arbitrary example, say your update takes 10 seconds, and the before/after code takes 1 second each: running it sync would block one thread for 12 seconds. Running it with await would use up two threads but for only one second each (so 12 thread-seconds* of processing vs 2) - technically calling 'await' and spinning up threads does have overhead, but it's negligible in comparison to what you're saving by using async/await. *a made up word for explanative purposes – The Lemon Dec 21 '22 at 04:25
  • @TheLemon Before = 1 sec. Then I call await which take 10 secs to complete. After 1 sec. The 3 occur consecutively. So I have to add up 1 + 10 + 1 = 12 secs when using await. – EBDS Dec 21 '22 at 07:32
  • @Crowcoder So it's up to ConfigureAwait to determine where the continuation thread runs. Thanks very much. – EBDS Dec 21 '22 at 07:36
  • @EBDS not really. Like I said, with ConfigureAwait(false) the the thread that resumes may *or may not be* the same as before awaiting. – Crowcoder Dec 21 '22 at 11:03
  • 1
    @EBDS you are getting some misleading info in this thread. I guess its the inherent vague nature of the English language. Simply put, just use async/await even if you don't understand all the nuances – Crowcoder Dec 21 '22 at 11:06
  • @Crowcoder Yes, I think there is some communication issues here. ha ha... – EBDS Dec 21 '22 at 13:47
  • @EBDS "So I have to add up 1 + 10 + 1 = 12 secs when using await." the method will take seconds but be using 0 system resources for 10 of them (ironically 'await' tells the thread not to wait) but crow's tldr; is correct, as a rule async/await is the way to go (a lot of newer resources do away with sync options for some functions altogether) - it's just gonna be painful for a few months as you figure out all the wrinkles – The Lemon Dec 22 '22 at 08:07
  • 1
    Settling the Biggest Await Async Debate in .NET https://youtu.be/aaC16Fv2zes – EBDS Dec 23 '22 at 08:44
  • not gonna lie, I face this dilemma all the time hahaha. I tend to do whatever feels right in the moment. Honestly though it doesn't matter in most real world scenarios - the performance difference is so slight it's not going to ever be what's bottlenecking you – The Lemon Dec 24 '22 at 12:25