Repository: dotnet/efcore
File: test/EFCore.Relational.Tests/Update/CommandBatchPreparerTest.cs (C#)

Code before:
        var entityB = new EntityB37169 { Id = "SOMEID", Name = "Any" };
        var entityBEntry = stateManager.GetOrCreateEntry(entityB);
        entityBEntry.SetEntityState(EntityState.Added);

        // Verify SharedIdentityEntry is set bidirectionally
        Assert.NotNull(entityBEntry.SharedIdentityEntry);
        Assert.Same(entityAEntry, entityBEntry.SharedIdentityEntry);
        Assert.NotNull(entityAEntry.SharedIdentityEntry);
        Assert.Same(entityBEntry, entityAEntry.SharedIdentityEntry);

        var modelData = new UpdateAdapter(stateManager);

        var commandBatches = CreateBatches(
            stateManager.GetEntriesToSave(cascadeChanges: true).ToArray(), modelData);

        // Should create valid batch(es) without errors
        Assert.NotEmpty(commandBatches);

        // Find the command for the replaced entity
        var allCommands = commandBatches.SelectMany(b => b.ModificationCommands).ToList();

        // The owned entity entry should be part of the same Modified command, not a separate Deleted command
        var deletedCommands = allCommands.Where(c => c.EntityState == EntityState.Deleted).ToList();
        Assert.Empty(deletedCommands);

        var modifiedCommand = Assert.Single(allCommands, c => c.EntityState == EntityState.Modified);

        // The modified command should contain both EntityB and OwnedEntity entries
        Assert.True(modifiedCommand.Entries.Count() >= 2,
            $"Expected at least 2 entries in Modified command, but got {modifiedCommand.Entries.Count()}. " +
            $"Total commands: {allCommands.Count}, states: [{string.Join(", ", allCommands.Select(c => c.EntityState))}]");

        // RowVersion should be a condition (used in WHERE clause)
        var rvModification = modifiedCommand.ColumnModifications
            .FirstOrDefault(cm => cm.ColumnName == "RowVersion");
        Assert.NotNull(rvModification);
        Assert.True(rvModification.IsCondition);
    }

    private abstract class EntityBase37169
    {
        public string Id { get; set; }
        public long RowVersion { get; set; }
    }

    private class OwnedEntity37169
    {
        public DateTime CreationDate { get; set; }
    }

    private class EntityA37169 : EntityBase37169

Review comment (bug):
`Assert.Single(allCommands, c => c.EntityState == EntityState.Modified)` only asserts there is exactly one Modified command, but allows additional commands of other states. Since the regression is about generating multiple commands for the same row, consider asserting the total command count (and/or the full set of states) to make the test fail on any unexpected extra commands.
```suggestion
        Assert.Single(allCommands);
        var modifiedCommand = Assert.Single(allCommands);
        Assert.Equal(EntityState.Modified, modifiedCommand.EntityState);
```

Code after:
        var entityB = new EntityB37588 { Id = "SOMEID", Name = "Any" };
        var entityBEntry = stateManager.GetOrCreateEntry(entityB);
        entityBEntry.SetEntityState(EntityState.Added);

        // Verify SharedIdentityEntry is set bidirectionally
        Assert.NotNull(entityBEntry.SharedIdentityEntry);
        Assert.Same(entityAEntry, entityBEntry.SharedIdentityEntry);
        Assert.NotNull(entityAEntry.SharedIdentityEntry);
        Assert.Same(entityBEntry, entityAEntry.SharedIdentityEntry);

        var modelData = new UpdateAdapter(stateManager);

        var commandBatches = CreateBatches(
            stateManager.GetEntriesToSave(cascadeChanges: true).ToArray(), modelData);

        // Should create valid batch(es) without errors
        Assert.NotEmpty(commandBatches);

        // Find the command for the replaced entity
        var allCommands = commandBatches.SelectMany(b => b.ModificationCommands).ToList();

        // The owned entity entry should be part of the same Modified command, not a separate Deleted command
        var deletedCommands = allCommands.Where(c => c.EntityState == EntityState.Deleted).ToList();
        Assert.Empty(deletedCommands);

        Assert.Single(allCommands);
        var modifiedCommand = Assert.Single(allCommands);
        Assert.Equal(EntityState.Modified, modifiedCommand.EntityState);

        // The modified command should contain both EntityB and OwnedEntity entries
        Assert.True(modifiedCommand.Entries.Count() >= 2,
            $"Expected at least 2 entries in Modified command, but got {modifiedCommand.Entries.Count()}. " +
            $"Total commands: {allCommands.Count}, states: [{string.Join(", ", allCommands.Select(c => c.EntityState))}]");

        // RowVersion should be a condition (used in WHERE clause)
        var rvModification = modifiedCommand.ColumnModifications
            .FirstOrDefault(cm => cm.ColumnName == "RowVersion");
        Assert.NotNull(rvModification);
        Assert.True(rvModification.IsCondition);
    }

    private abstract class EntityBase37588
    {
        public string Id { get; set; }
        public long RowVersion { get; set; }
    }

    private class OwnedEntity37588
    {
        public DateTime CreationDate { get; set; }
    }