Skip to content

Can't change state of entity with complex collection #37724

@ArnaudB88

Description

@ArnaudB88

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

Metadata

Metadata

Assignees

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions