EF Core Change Tracking Mechanism Fail to update Entity Tracking internal Info on just Added Entity if pk field values change after entity being added to context
EF Core Change Tracking Mechanism Fail to update Entity Tracking internal Info on just Added Entity if pk field values change after entity being added to context but not yet persisted with save changes.
Actual behaviour and description of the problem:
when an entity is added to a context the change tracker mechanism begin tracking the entity using the actual pk field values (even on single or composite primary key) and the entity state is set to Added. Then, after this, if some or all primary key fields values are changed without saving the changes, the internal tracking info should be updated to reflect the new pk field values, This is not happening, EF Core still track the entity for the values captured when the context.Add() method is called. Now if the if another entity is initialized with the first initial values, EF CORE get confused by thinking there is another entity in context with the same tracking pk fields original values which is no longer true and throws exception.
Expected behaviour: After updating an entity with state Added (therefore not yet persisted), EF CORE should watch for changes on pk field values and keep track of new values because the entity pk fields are now not the previous ones.
In other words, on added entities, the internal tracking info could get misaligned with entity pk properties values if changed just after adding the entity to the context.
This could be problematic if the DB structure cannot be changed to workaround the issue. please note also that because the entity being added must have not null values for pk fields we were forced to supply default values and later change those pk properties (that therefore may change) before saving changes.
Steps to Reproduce: Decompress the attached project. Change the connection information to connect to a SQL Server database that should have a table defined like this:
` USE [track] GO
/****** Object: Table [dbo].[TrackFail] Script Date: 18/04/2024 14:47:27 ******/ SET ANSI_NULLS ON GO
SET QUOTED_IDENTIFIER ON GO
CREATE TABLE [dbo].[TrackFail]( [CompositePK1] nvarchar NOT NULL, [CompositePK2] nvarchar NOT NULL, [DummyData] nvarchar NULL, CONSTRAINT [PK_TrackFail] PRIMARY KEY CLUSTERED ( [CompositePK1] ASC, [CompositePK2] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY] GO
`
Run the project. The code try to add a inititialized entity with default values, then change pk properties or values and try to add another entity with default values. Because we just changed the first's entity pk values EF CORE should accept the second call to add() method instead it does throw exception because it does think that the first entity is still tracked with default initialized values which of course, is no longer true.
Include provider and version information
EF Core version 6 or later: BugEF.zip Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: NET 6.0 or later Operating system: IDE: Visual Studio 2022 Version 17.9.6
@b-giavotto This is by-design. If the PK values are changed, then EF needs to be informed of this change by calling DetectChanges. For example:
firstEn.CompositePK1 = "A";
firstEn.CompositePK2 = "B";
ctx2.ChangeTracker.DetectChanges();
var secondEn = AddNewDefaultEntity(ctx2);
We don't do this automatically because detecting changes can be expensive, and it is extremely rare to need to do it before calling Add, but this is one such case.