dotnet / dotnet/efcore

Primitive collections don't support ChangingAndChangedNotifications ChangeTrackingStrategy

Open
#36,052 1 comment 1 reaction 1 assignee Claimed by @AndriySvyryd View on GitHub
area-change-tracking area-primitive-collections customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

### Bug description

We use
`entity.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotifications);`
to generate efficient update statements in efcore. We set the track changes strategy in the EntityTypeConfiguration, and use update code like this:

```
var context = new dbContext();
var poco = new Poco() { Key = 1 };
context.Attach(poco);
poco.SomePropertyToUpdate = 2;
context2.SaveChanges();
```

this generates a (in our case mssql) update statement that specifically updates the SomePropertyToUpdate, and leaves other properties alone, and not having to do a query to get the current values before saving.

However, once we add a primitive (json) collection to our Poco, we cannot save anymore, because ef core enforces us to give the primitive collection a value:

```
The primitive collection property 'TestEntity.PrimitiveGuid' is configured as required (non-nullable) but has a null value when saving changes. Either mark the property as optional (nullable) or set a non-null value.
```

I've added a simple reproduction scenario demonstrating the issue. This behavior blocks us from using primitive collections altogether. Filling the collection with an empty collection before attaching it to dbcontext is a workaround that works for mssql provider.

### Your code

[EFCoreIssue.zip](https://github.com/user-attachments/files/20103323/EFCoreIssue.zip)

### Stack traces

```text
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.g__CheckForNullCollection|113_1(IProperty property, <>c__DisplayClass113_0& )
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.PrepareToSave()
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.GetEntriesToSave(Boolean cascadeChanges)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(StateManager stateManager, Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<>c.b__112_0(DbContext _, ValueTuple`2 t)
at Microsoft.EntityFrameworkCore.Storage.NonRetryingExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
at Program.<$>g__ThisBreaks|0_1() in D:\local projects\EFCoreIssue\Program.cs:line 46
at Program.$(String[] args) in D:\local projects\EFCoreIssue\Program.cs:line 6
```

### Verbose output

```text

```

### EF Core version

9.0.4

### Database provider

Microsoft.EntityFrameworkCore.SqlServer

### Target framework

.Net 9

### Operating system

Windows 11

### IDE

Visual studio 17.13.6

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.