dotnet / dotnet/efcore

EF core tries to update Alternate Key SQL identity column.

Open
#32,800 13 comments 0 reactions 0 assignees View on GitHub
area-migrations area-model-building customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

Given the following entity

```
public class MyEntity {
public virtual Guid PersistenceId { get; private set; }
public virtual int MyEntityId { get; private set; }
public virtual string Name { get; set; }
}
```

Using fluent API for EF configuration

```
public class MyEntityConfig : IEntityTypeConfiguration {
public void Configure(EntityTypeBuilder builder) {
builder.ToTable("MyEntities");

builder.HasKey(x => x.PersistenceId);
builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd().HasDefaultValueSql("newid()");

builder.HasAlternateKey(x => x.MyEntityId);
builder.Property(x => x.MyEntityId).ValueGeneratedOnAdd();

builder.Property(x => x.Name).HasMaxLength(100);
}
}
```

Everything works as intended when the entity is first added to the database. When the entity is updated and changes are saved back to the database, SQL Server throws an exception "cannot update identity column 'MyEntityId'.

```
Message: 
Microsoft.EntityFrameworkCore.DbUpdateException : An error occurred while saving the entity changes. See the inner exception for details.
---- Microsoft.Data.SqlClient.SqlException : Cannot update identity column 'MyEntityId'.

Stack Trace: 
ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
SqlServerModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
<5 more frames...>
<>c.b__209_0(Task`1 result)
ContinuationResultTaskFromResultTask`2.InnerInvoke()
ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
```

It appears like EF Core is sending the MyEntityId column in the update statement even though it's marked as an AlternateKey with ValueGeneratedOnAdd.

EF Core version: 8.0.1
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 8.0
Operating system: Windows 10 22H2
IDE: Visual Studio 2022 17.8.2

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.