-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Closed
Milestone
Description
When using Attach and IsModified to update column without first fetching whole entity from database, SaveChanges throws circular dependency in unique unfiltered index, even if updated column is not part of the index. This code works fine in ef core 6.
Repro steps
[Fact]
public void SaveChangesShouldNotThrow()
{
var context = new TestDbContext();
var e = new TestEntity { Id = Guid.NewGuid(), Name = "n1" };
var e2 = new TestEntity { Id = Guid.NewGuid(), Name = "n2" };
context.TestEntities.Attach(e);
context.TestEntities.Attach(e2);
context.Entry(e).Property(p => p.Name).IsModified = true;
context.Entry(e2).Property(p => p.Name).IsModified = true;
context.SaveChanges();
}
public class TestDbContext : DbContext
{
public DbSet<TestEntity> TestEntities { get; set; }
protected override void OnConfiguring(
DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured || optionsBuilder.Options.Extensions.Count() <= 1)
{
optionsBuilder.UseSqlServer("Server=.;Initial Catalog=test;User Id=sa;Password=test;TrustServerCertificate=true");
base.OnConfiguring(optionsBuilder);
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<TestEntity>()
.HasKey(t => t.Id);
modelBuilder.Entity<TestEntity>()
.HasIndex(t => new { t.Id1, t.Id2 })
.IsUnique();
}
}
public class TestEntity
{
public Guid Id { get; set; }
public string Name { get; set; }
public Guid Id1 { get; set; }
public Guid Id2 { get; set; }
}
Stack trace
System.InvalidOperationException
Unable to save changes because a circular dependency was detected in the data to be saved: 'TestEntity [Modified] <-
Index { 'Id1', 'Id2' } TestEntity [Modified] <-
Index { 'Id1', 'Id2' } TestEntity [Modified]To show additional information call 'DbContextOptionsBuilder.EnableSensitiveDataLogging'.'.
at Microsoft.EntityFrameworkCore.Utilities.Multigraph`2.ThrowCycle(List`1 cycle, Func`2 formatCycle, Func`2 formatException)
at Microsoft.EntityFrameworkCore.Utilities.Multigraph`2.TopologicalSortCore(Boolean withBatching, Func`4 tryBreakEdge, Func`2 formatCycle, Func`2 formatException)
at Microsoft.EntityFrameworkCore.Utilities.Multigraph`2.BatchingTopologicalSort(Func`4 tryBreakEdge, Func`2 formatCycle, Func`2 formatException)
at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.TopologicalSort(IEnumerable`1 commands)
at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.BatchCommands(IList`1 entries, IUpdateAdapter updateAdapter)+MoveNext()
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IList`1 entries)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList`1 entriesToSave)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(StateManager stateManager, Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<>c.<SaveChanges>b__107_0(DbContext _, ValueTuple`2 t)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.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()**
**
Include provider and version information
EF Core version:
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 7.0.202, ef core 7.0.3 (it was working fine in ef core 6.*)