Reputation: 16841
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.
Upvotes: 4
Views: 3377
Reputation: 205539
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 thoughblog.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.
Upvotes: 13
Reputation: 4839
I've never seen linking entities in EF Core using the temporary id.
Typically what you would do is assign the entity and let EF sort out the ids and relationships.
i.e. in this instance, the School
will be linked to the Person
.
await _dbContext.AddAsync(person);
School school = mySchool;
school.Person = person;
await _dbContext.AddAsync(school);
await _dbContext.SaveChangesAsync();
Upvotes: 3