When setting a related entity to a default value via the constructor. I.e.:
public Blog() {
this.Author = new Author();
}
the property does not get replaced correctly with the entity that was retrieved from the database. Thus all changes to it are lost on SaveChanges.
This worked correctly in EF core 3.1.
Run this project
EFCoreCtorBug.zip
Output: "Author Name:"
Switch to EF core 3.1
Output: "Author Name: NonMVPAuthor"
Notice how the Author property is not replaced with the object retrieved from the database on line 29 but instead is the default object set in the ctor.
EF Core version: 5.0 RC1
Database provider: seems to be universal to all providers.
Target framework: .NET Core 3.1
Duplicate of dotnet/efcore#18007
As far as I understand dotnet/efcore#18007 this is not a bug but the current expected behavior?
If setting dependent entities to a default entity in the constructor causes such unexpected and inconsistent behaviours, shouldn't EF core at least throw an exception for such cases? It shouldn't be hard to detect ctor-initialized entities.
@ChristophHornung I am able to reproduce this; looks like a regression of dotnet/efcore#18007 in 5.0. I will investigate,
Notes for team:
So we could choose to:
Also, there may be a feasible to determine in a performant way that an existing object instance was used instead of the one returned from the query. We should investigate this a bit more for a future release.
@ajcvickers if this is going to be documented as a breaking change from EFCore 3.1 to EFCore 5.0 what is the recommended way to set a default value for a relation in EFCore 5.0? The current EFCore 3.1 behavior is not only more useful but also consistent with the behavior from other popular ORMs such as Hibernate and Doctrine.
@daniel3303 Yes, this will be documented. EF Core doesn't support creating a default instance of an entity types since this implies a default key value. The discussion in https://github.com/dotnet/efcore/issues/18007 covers this.
Also, there may be a feasible to determine in a performant way that an existing object instance was used instead of the one returned from the query. We should investigate this a bit more for a future release.
@ajcvickers Is there an open issue that covers this investigation?
@ChristophHornung We're not actively investigating this currently. I will create an issue.
Most helpful comment
@ajcvickers if this is going to be documented as a breaking change from EFCore 3.1 to EFCore 5.0 what is the recommended way to set a default value for a relation in EFCore 5.0? The current EFCore 3.1 behavior is not only more useful but also consistent with the behavior from other popular ORMs such as Hibernate and Doctrine.