Entityframework.docs: Document additional behavior change in 5.0 when a reference navigation property is set eagerly by the entity instance

Created on 22 Sep 2020  路  8Comments  路  Source: dotnet/EntityFramework.Docs

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.

Steps to reproduce

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.

Further technical details

EF Core version: 5.0 RC1
Database provider: seems to be universal to all providers.
Target framework: .NET Core 3.1

area-change-tracking closed-fixed type-breaking-change

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.

All 8 comments

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:

  • This is a breaking change in behavior from 3.1 to 5.0. Even though most of dotnet/efcore#18007 was fixed in 3.0, we made the behavior more consistent in 5.0 which results in not replacing the existing entity when materializing from the query.
  • I went back to EF6 to check again the behavior there. It's not consistent. For this case with an FK relationship, EF6 behaves like EF Core 5.0. Conversely, EF6 with an independent relationship behaves like EF Core 3.1. I suspect this is a bug in EF6 with independent relationships, since they were less tested in later releases.

So we could choose to:

  • Revert the change in behavior in 5.0 as a break. However, this would leave us in a inconsistent place.
  • Document the change in 5.0 as breaking change.

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

CeciAc picture CeciAc  路  4Comments

MohammadMQ picture MohammadMQ  路  3Comments

divega picture divega  路  3Comments

speciesunknown picture speciesunknown  路  3Comments

weitzhandler picture weitzhandler  路  4Comments