72

Ok multiple questions here:

  • I am trying to understand what is the difference (outside the obvious asynchronous) between AddAsync() and Add() methods in EF Core?

  • When do you choose one over the other?

  • Does it matter if you choose one over the other for consistency?

Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
Aeseir
  • 7,754
  • 10
  • 58
  • 107
  • 2
    All answered in the docs: https://learn.microsoft.com/en-us/ef/core/change-tracking/miscellaneous#add-versus-addasync – Gert Arnold Jul 24 '22 at 15:34

3 Answers3

74

After going through the code I agree with Henk Holterman's comment that using Add() when your code is async is an optimization. The documentation for AddAsync() is a little misleading when it says, "For all other cases the non async method should be used".

I am trying to understand what is the difference (outside the obvious asynchronous) between AddAsync() and Add() methods in EF Core?

AddAsync() is 100% async safe, while Add() is only async safe in certain conditions. Like the comment implies, one of your columns may be configured such that Entity Framework makes a query to the database to generate the value that will eventually be inserted. In that case, blocking would occur if you called Add().

When do you choose one over the other?

  • If you're not writing async code, then definitely use Add().
  • If you're writing async code and want to keep things simple, choose AddAsync() just as you would for other methods.
  • If you really want to avoid the overhead of async calls and you know Add() will never make a database query, then use Add().

Does it matter if you choose one over the other for consistency?

No, despite the recommendation in the AddAsync() documentation.

Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
snakey
  • 774
  • 6
  • 2
  • 3
    What if I am using an id generator, should I use the `AddAsync` then? I mean if the PK for my rows is an int which is generated by the db. Or will there be no difference if I use the `Add`? – manymanymore May 11 '20 at 17:56
  • This matters a bit if you want to return the object after AddAsync(). You can do Add(entity).Entity, which presumably returns generated properties like the primary key, although I am not 100% sure. – perustaja Jan 05 '21 at 18:59
  • This answer saved me some headache and finally helped me realize this is the cause of my non-deterministic concurrency issues. I'm using Postgres with most of my entities using db-provided IDs. I kept running into error `System.InvalidOperationException : A second operation was started on this context instance before a previous operation completed`. Turns out I was using all `Add()` thinking it wasn't doing anything behind the scenes - once I tried out `AddAsync()` the concurrency issues went away! – SIRHAMY Jul 08 '22 at 23:19
  • 1
    The only thing is, I don't think there are any hooks that allow *user* code to run while `AddAsync` is executed. So the statement "For all other cases the non async method should be used" is valid and is better adhered to. – Gert Arnold Jul 24 '22 at 15:29
  • This answer is very misleading, because it is incorrect for the vast majority of EFCore usecases. It's only correct when the HiLo ID generation is configured (which is very rare). Check the documentation: https://learn.microsoft.com/en-us/ef/core/change-tracking/miscellaneous#add-versus-addasync – ErroneousFatality Dec 01 '22 at 09:28
28

From the source code:

This method is async only to allow special value generators, such as the one used by 'Microsoft.EntityFrameworkCore.Metadata.SqlServerValueGenerationStrategy.SequenceHiLo', to access the database asynchronously. For all other cases the non async method should be used.

So if you use a value generator that might need to access the DB to get new values to assign to new entries, such as the SequenceHiLo generator, then use AddAsync().

juunas
  • 54,244
  • 13
  • 113
  • 149
  • I don't get the advice on your last line. Surely the choice depends on your Identity system, not on EF vs EfCore. I always use AddAsync() . In case of doubt you probably should, Add() is an optimization. – H H Nov 06 '17 at 13:11
  • I actually misread the line in the documentation :) Thanks for the comment. Indeed, it depends on if you are using a value generator that might need to access the database. – juunas Nov 06 '17 at 13:20
  • Just to clarify - Using a value generator which generates a value in the _project_ but needs access to the database? This, then, would not include the Identity columns, for example, since they are computed by the database and not the program. Correct? – LiHRaM Dec 15 '17 at 21:18
  • 2
    Right, an identity column is computed on insert and thus you can use Add(). – juunas Dec 22 '18 at 08:58
6

It all depends on what you want?

AddAsync() makes sense to call if you are using an algorithm Hi/Lo. In all other cases, call sync Add().

It is important to understand that this is not some kind of EF feature, this is an old technique for working with a database. The choice of this technique has a profound effect on your data design. Therefore, it is more a matter of your approach to working with data, not sync-async code.

Here is a good description Hi/Li:

https://www.talkingdotnet.com/use-hilo-to-generate-keys-with-entity-framework-core/

What's the Hi/Lo algorithm?

sergeyxzc
  • 515
  • 6
  • 4