Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Self-referencing entity circular dependency happening just on EF Core 6.0 #26750

Closed
josecu08 opened this issue Nov 18, 2021 · 4 comments
Closed
Labels
area-save-changes closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression Servicing-approved type-bug
Milestone

Comments

@josecu08
Copy link

Description

I'm not sure at all if this is a bug. At least I think is an unexpected behavior.
This behavior appeared for the first time after migrating to NET 6. I've managed to reproduce the issue in the simple project composed of the 3 files shown bellow. First I thought it was a breaking change so I reviewed all of them. However, I'm unable to find any breaking change that would cause this error. As I wasn't able to relate the error to any change I started changing efcore version in my .csproj file. As soon as I change to 6.0.0-rc.2.21480.5 for all the packages (efcore) the error doesn't show anymore. Another thing to highlight is that if I add a SaveChanges after the removes in the program.cs file the error won't happen either.

Person.cs

#nullable disable
public class Person
{
    public int PersonId { get; set; }
    public string Name { get; set; }
    public int? ParentId { get; set; }
    public Person Parent { get; set; }


    protected Person()
    {
        
    }
    
    public Person(string name, Person parent)
    {
        this.Name = name;
        if (parent is not null)
        {
            this.Parent = parent;
        }
    }
}

Context.cs

#nullable disable
using Microsoft.EntityFrameworkCore;

public class Context : DbContext
{
    public Context()
    {}

    public DbSet<Person> Parents { get; set; }

    protected override void OnConfiguring(
            DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(
            "Data Source=DES04;Initial Catalog=Test;Integrated Security=true");        
        base.OnConfiguring(optionsBuilder);
    }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>()
            .HasOne(p => p.Parent)
            .WithMany()
            .IsRequired(false)
            .OnDelete(DeleteBehavior.Restrict);

        modelBuilder.Entity<Person>()
            .HasKey(p => p.PersonId);
    }
}

Program.cs

var context = new Context();

var parent = new Person("1", null);
var child1 = new Person("2", parent);
var child2 = new Person("3", parent);
var grandchild1 = new Person("4", child1);
var grandchild2 = new Person("5", child1);
var grandchild3 = new Person("6", child2);
var grandchild4 = new Person("7", child2);

context.Add(parent);
context.Add(child1);
context.Add(child2);
context.Add(grandchild1);
context.Add(grandchild2);
context.Add(grandchild3);
context.Add(grandchild4);
context.SaveChanges();


context.Remove(parent);
context.Remove(child1);
context.Remove(child2);
context.Remove(grandchild1);
context.Remove(grandchild2);
context.Remove(grandchild3);
context.Remove(grandchild4);

parent = new Person("1", null);
child1 = new Person("2", parent);
child2 = new Person("3", parent);
grandchild1 = new Person("4", child1);
grandchild2 = new Person("5", child1);
grandchild3 = new Person("6", child2);
grandchild4 = new Person("7", child2);

context.Add(parent);
context.Add(child1);
context.Add(child2);
context.Add(grandchild1);
context.Add(grandchild2);
context.Add(grandchild3);
context.Add(grandchild4);
context.SaveChanges();

Stack trace

Unhandled exception. System.InvalidOperationException: Unable to save changes because a circular dependency was detected in the data to be saved: 'Person [Deleted]Person [Deleted] Parent { 'ParentId' } <-
Person [Deleted] Parent { 'ParentId' } <-
Person [Deleted]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.BatchingTopologicalSort(Func`4 tryBreakEdge, Func`2 formatCycle)
   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__104_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()
   at Program.<Main>$(String[] args) in C:\Users\Dev04\Desktop\Nueva carpeta\test\Program.cs:line 44

Version information

EF Core version:
Ef Core (Microsoft.EntityFrameworkCore 6.0.0)
Database provider: (Microsoft.EntityFrameworkCore.SqlServer 6.0.0)
Target framework: (.NET 6.0.0)

@ajcvickers
Copy link
Member

/cc @AndriySvyryd Throws on 6.0; does not throw on 5.0.

@jonasrdm
Copy link

I'm having the same issue in my project after the upgrade. Does it have any known workaround until a fix is released?

@ajcvickers
Copy link
Member

@jonasrdm We will investigate workarounds.

@fengqingtian
Copy link

I'm having the same issue in my project after the upgrade. Does it have any known workaround until a fix is released?
in my situation, I add another context.SaveChanges() before add, it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-save-changes closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression Servicing-approved type-bug
Projects
None yet
Development

No branches or pull requests

5 participants