-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Description
Bug description
I am trying to change the state of a deleted entity to 'Unchanged' and it gives an exception:
Complex entry ordinal '-1' is invalid for the collection 'Financieringslijn[]KolomMetadata.KolomMetadata' as it's outside of the collection of length '6'.
Why
As suggested in the EfCore 10 release notes, we are migrating from owned entities (saved as json) to complex entity types. This results in several problems, and the bug described here is one of them.
Scenario
We use a soft-delete approach on all tables in our database. We achieve this by first setting an entity to the state 'Deleted'. Afterwards when we want to save our changes, we change the state again to 'Unchanged' and update some soft delete properties.
When the state is changed from 'Deleted' to 'Unchanged', an exception occurs.
Note: the exception does not occur when changing the state from 'Deleted' to 'Modified'.
Your code
//entity
public partial class Financieringslijn
{
public Guid Id { get; set; }
//other properties
public IList<KolomMetadata> KolomMetadata { get; set; }
}
//Mappings
public partial class FinancieringslijnMap
: IEntityTypeConfiguration<Interreg.Eloket.Domain.Entities.Financieringslijn>
{
public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder<Interreg.Eloket.Domain.Entities.Financieringslijn> builder)
{
builder.ToTable("Financieringslijn", "dbo");
builder.HasKey(t => t.Id);
//other mappings
builder.ComplexCollection(t => t.KolomMetadata, builder => builder.ToJson().Configure());
//Note: the Configure() method sets the property names of the KolomMetadata to camelCase
}
}
//Scenario
//Add new entity
var line = new Financieringslijn();
dbContext.Set<Financieringslijn>.Add(line);
await dbContext.SaveChangesAsync();
//Try to delete the entity
var lineToDelete = await dbContext.Set<Financieringslijn>.FindAsync(line.Id);
var dbEntry = dbContext.Entry(lineToDelete);
dbEntry.State = EntityState.Deleted;
//Change entry to allow 'soft delete logic'
var entities = ChangeTracker.Entries<IEntityBase>()
.Where(p => p.State == EntityState.Added || p.State == EntityState.Modified || p.State == EntityState.Deleted);
//(some other logic here for added and modified entities)
foreach (var deleted in entities.Where(e => e.State == EntityState.Deleted))
{
var dbEntityEntry = dbContext.Entry(deleted.Entity);
dbEntityEntry.State = EntityState.Unchanged; // Exception occurs
deleted.Entity.Deleted = true;
deleted.Entity.DeletedBy = "current user";
deleted.Entity.DeletedDate = DateTimeOffset.Now;
}Stack traces
System.InvalidOperationException
HResult=0x80131509
Message=Complex entry ordinal '-1' is invalid for the collection 'Financieringslijn[]KolomMetadata.KolomMetadata' as it's outside of the collection of length '6'.
Source=Microsoft.EntityFrameworkCore
StackTrace:
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntryBase.InternalComplexCollectionEntry.ValidateOrdinal(InternalComplexEntry entry, Boolean original, List`1 entries)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntryBase.InternalComplexCollectionEntry.ValidateOrdinal(InternalComplexEntry entry, Boolean original)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntryBase.ValidateOrdinal(InternalComplexEntry entry, Boolean original)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalComplexEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntryBase.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey, Nullable`1 fallbackState)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntryBase.SetPropertyModified(IComplexProperty property, Boolean isModified, Boolean recurse)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntryBase.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey, Nullable`1 fallbackState)
at Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry.set_State(EntityState value)
at ClientName.ProjectName.Repositories.EntityFrameworkEntitiesDbContext.SetHistoryFields() in C:\Projects\ClientName\ProjectName\ClientName.ProjectName.Repositories\EntityFrameworkEntitiesDbContext.cs:line 429
at ClientName.ProjectName.Repositories.EntityFrameworkEntitiesDbContext.<SaveDbContextChangesAsync>d__13.MoveNext() in C:\Projects\ClientName\ProjectName\ClientName.ProjectName.Repositories\EntityFrameworkEntitiesDbContext.cs:line 146
at ClientName.ProjectName.Repositories.EntityFrameworkUnitOfWork.<ExecuteWithSaveDbContextChangesAsync>d__14.MoveNext() in C:\Projects\ClientName\ProjectName\ClientName.ProjectName.Repositories\EntityFrameworkUnitOfWork.cs:line 91
at ClientName.ProjectName.Tests.BusinessManagerTests.FinancieringsplanManagerTests.<GetFinplannenGevalideerdDoorInternCachedAsync_Should_Work>d__1.MoveNext() in C:\Projects\ClientName\ProjectName\ClientName.ProjectName.Tests\BusinessManagerTests\FinancieringsplanManagerTests.cs:line 54
at Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Execution.TestMethodInfo.<ExecuteInternalAsync>d__55.MoveNext()
EF Core version
10.0.3
Database provider
Microsoft.EntityFrameworkCore.SqlServer
Target framework
.NET 10
Operating system
Windows 11
IDE
Visual Studio 2026 18.2.1