Skip to content

Stack overflow when saving multiple modified entities with the same key #23043

Closed

Description

EF Core version: 5.0.0-rc.2.20475.6
Database provider: Microsoft.EntityFrameworkCore.Sqlite
Target framework: net5.0

Example.csproj

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-rc.2.20475.6" />
    </ItemGroup>
</Project>

Program.cs

public class BloggingContext : DbContext
{
      private DbConnection _connection;

      public DbSet<Blog> Blogs { get; set; }
      public DbSet<Post> Posts { get; set; }

      protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
      {
            optionsBuilder.UseSqlite(CreateDatabaseAndGetConnection());
      }

      private DbConnection CreateDatabaseAndGetConnection()
      {
            _connection = new SqliteConnection("Data Source=:memory:");
            _connection.Open();

            using (var context = new BloggingContext())
            {
                  context.GetService<IRelationalDatabaseCreator>().CreateTables();
            }

            return _connection;
      }

      public override void Dispose()
      {
            base.Dispose();
            _connection.Dispose();
      }
}

public class Blog
{
      public int BlogId { get; set; }
      public string Url { get; set; }
      public List<Post> Posts { get; set; }
}

public class Post
{
      public int PostId { get; set; }
      public string Title { get; set; }

      public int BlogId { get; set; }
}

class Program
{
      static void Main(string[] args)
      {
            using (var db = new BloggingContext())
            {
                  db.Database.Migrate();
            }

            using (var db = new BloggingContext())
            {
                  var blog = new Blog
                  {
                        BlogId = 1,
                        Url = "http://sample.com",
                        Posts = new List<Post>()
                        {
                              new Post()
                              {
                                    PostId = 1,
                                    Title = "title1"
                              },
                              new Post()
                              {
                                    PostId = 2,
                                    Title = "title2"
                              }
                        }
                  };

                  db.Blogs.Add(blog);
                  db.SaveChanges();
            }

            using (var db = new BloggingContext())
            {
                  var blog = db.Blogs.Include(x => x.Posts).First(x => x.BlogId == 1);

                  blog.Posts.Clear();

                  blog.Posts.AddRange(new List<Post>()
                  {
                        new Post()
                        {
                              PostId = 1,
                              Title = "title1"
                        },
                        new Post()
                        {
                              PostId = 2,
                              Title = "title2"
                        }
                  });

                  db.SaveChanges();
            }


            Console.WriteLine("Hello World!");
      }
}

dotnet build

C:\Example>dotnet build
Microsoft (R) Build Engine version 16.8.0-preview-20475-05+aed5e7ed0 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
  You are using a preview version of .NET. See: https://aka.ms/dotnet-core-preview
  Example -> C:\Example\bin\Debug\net5.0\Example.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.83

dotnet run

C:\Example>dotnet run
Stack overflow.

It seems that the AcceptChanges method caused the endless loop.

SharedIdentityEntry?.AcceptChanges();

public virtual void AcceptChanges()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions