Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EFCore adding temporary ID by AddAsync()

I am using EFCore 5.0.0.

When I AddAsync (person); I should be getting a temporary ID, and I use this ID to add the PersonId for School (shown in code below). FInally, I will SaveChangesAsync() where everything will be saved. However, the PersonId is set to 0. I want to get the temporary ID stored instead. How can I do this.

await _dbContext.AddAsync(person);

School school = mySchool;
school.PersonId = person.Id;
await _dbContext.AddAsync(school);

await _dbContext.SaveChangesAsync();

Note: There are many SO post that talks about the temporary ID, but none is related to this post.

like image 229
Illep Avatar asked Sep 02 '25 16:09

Illep


1 Answers

Currently accepted answer is valid, but technically incorrect. Assigning navigation property is valid approach, but not mandatory. It's even perfectly valid to not have navigation property at all. As well as explicit FK property. But there is always at least shadow FK property which can be used to setup/maintain the relationship.

So the temporary key concept is part of the EF Core from the very beginning. However EF Core 3.0 introduced a breaking change - Temporary key values are no longer set onto entity instances. The link contains an explanation of the old and new behaviors, the reason and possible solutions:

Applications that assign primary key values onto foreign keys to form associations between entities may depend on the old behavior if the primary keys are store-generated and belong to entities in the Added state. This can be avoided by:

  • Not using store-generated keys.
  • Setting navigation properties to form relationships instead of setting foreign key values.
  • Obtain the actual temporary key values from the entity's tracking information. For example, context.Entry(blog).Property(e => e.Id).CurrentValue will return the temporary value even though blog.Id itself hasn't been set.

Bullet #1 makes no sense, Bullet #2 is what is suggested in the other answer. Bullet #3 is the direct answer/solution to your question.

And applying it to your example requires just changing

school.PersonId = person.Id;

to

school.PersonId = _dbContext.Entry(person).Property(e => e.Id).CurrentValue;

Of course when you have navigation property and the related entity instance, it's better to use it and let EF Core do its magic. The temporary key is really useful when you don't have navigation property, or you don't have related entity instance and know the key, but don't want to do roundtrip to load it from database (and using fake stub entity instance can lead to unexpected side effects/behaviors). It works well with both explicit and shadow FK properties.

like image 180
Ivan Stoev Avatar answered Sep 05 '25 04:09

Ivan Stoev