You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An aggregate root has a 1:0..1 optional dependent with some required properties, using table splitting. This dependent entity has a 1:1 required dependent where all properties are nullable (that's why this nav is required). After the optional dependent has saved values, changes on the required dependent entity are not saved.
Steps to reproduce
Build & run.
Observe the last issued SQL command and "State before save:" line on the console output.
If the required dependent is replaced: "State before save: Added" and an update command.
If the required dependent is reused: "State before save: Detached" and no update command.
(note that both City and Street columns are updated in the former case despite the Street not changing)
using Microsoft.EntityFrameworkCore;using Microsoft.Extensions.Logging;// Prep the db & seedusing(vardb=new AppDb()){
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
db.Parents.Add(new(){Id="x",Child=new(){Name="asd"}});
db.SaveChanges();}// reproduce the issueusing(vardb=new AppDb()){varparent= db.Parents.Single();// This will update//parent.Child!.Address = new() { City = "asd" };// This will not
parent.Child!.Address.City ="asd";
db.ChangeTracker.DetectChanges();
Console.WriteLine($"State before save: {db.Entry(parent.Child.Address).State}");
db.SaveChanges();}// ModelclassAppDb:DbContext{protectedoverridevoidOnConfiguring(DbContextOptionsBuilderbuilder){
builder
.UseSqlServer("Data Source=localhost;Initial Catalog=Test;Integrated Security=true").LogTo(Console.WriteLine, LogLevel.Information).EnableSensitiveDataLogging();}protectedoverridevoidOnModelCreating(ModelBuilderbuilder){
builder.Entity<Parent>().OwnsOne(e => e.Child).OwnsOne(e => e.Address);}publicDbSet<Parent> Parents =>this.Set<Parent>();}classParent{publicrequiredstringId{get;set;}publicChild?Child{get;set;}}classChild{publicrequiredstringName{get;set;}publicAddressAddress{get;set;}=new();}classAddress{// All optional, hence the navigation to this entity is requiredpublicstring?City{get;set;}publicstring?Street{get;set;}}
First I thought this has to do with owned entities and thus part of #24581 and #1985 however it repros with plain old navigations. Replace OnModelCreating with the following (basically maps to the same table structure), steps and outcome is the same
the navigation is required but warns OptionalDependentWithAllNullPropertiesWarning[20704] and neither the Address nor the City and Street setters are hit on materialization
the Address is Detached on materialization, it should be Unchanged
even though Detached the change tracker still maintains some knowledge of the Address or else the replace/reuse behavior could not be possibly different. It's just an unknown object.
An aggregate root has a 1:0..1 optional dependent with some required properties, using table splitting. This dependent entity has a 1:1 required dependent where all properties are nullable (that's why this nav is required). After the optional dependent has saved values, changes on the required dependent entity are not saved.
Steps to reproduce
Build & run.
Observe the last issued SQL command and "State before save:" line on the console output.
If the required dependent is replaced: "State before save: Added" and an update command.
If the required dependent is reused: "State before save: Detached" and no update command.
(note that both City and Street columns are updated in the former case despite the Street not changing)
First I thought this has to do with owned entities and thus part of #24581 and #1985 however it repros with plain old navigations. Replace OnModelCreating with the following (basically maps to the same table structure), steps and outcome is the same
Some additional observations:
Include provider and version information
EF Core version: 8.0.8
Database provider: Microsoft.EntityFrameworkCore.SqlServer (probably others)
Target framework: .NET 8.0
The text was updated successfully, but these errors were encountered: