-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Stack overflow when saving multiple modified entities with the same key #23043
Comments
@maliming You're creating a new Note for triage: we detect and throw a better message when the same context instance is used while it is being configured. In this case it is a different context instance each time. We may be able to detect and throw a better message in this case too. |
hi @ajcvickers I actually encountered another problem, I will try to reproduce it. |
hi Output a lot of Although my code is unconventional, better error messages will help. : ) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.AcceptChanges()
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.AcceptChanges()
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.AcceptAllChanges(System.Collections.Generic.IReadOnlyList`1<Microsoft.EntityFrameworkCore.Update.IUpdateEntry>)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Microsoft.EntityFrameworkCore.DbContext, Boolean)
at Microsoft.EntityFrameworkCore.Storage.NonRetryingExecutionStrategy.Execute[[System.Boolean, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Int32, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](Boolean, Syste
m.Func`3<Microsoft.EntityFrameworkCore.DbContext,Boolean,Int32>, System.Func`3<Microsoft.EntityFrameworkCore.DbContext,Boolean,Microsoft.EntityFrameworkCore.Storage.ExecutionResult`1<Int32>>)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
at Example.Program.Main(System.String[]) public static class SqliteMemoryConnection
{
public static readonly SqliteConnection Connection;
static SqliteMemoryConnection()
{
Connection = new SqliteConnection("Data Source=:memory:");
Connection.Open();
}
}
public class BloggingContext : DbContext
{
public static DbContextOptions Options;
public BloggingContext(DbContextOptions options)
:base(options)
{
}
public BloggingContext()
{
}
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite(SqliteMemoryConnection.Connection);
}
}
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 context = new BloggingContext(new DbContextOptionsBuilder().UseSqlite(SqliteMemoryConnection.Connection).Options))
{
context.GetService<IRelationalDatabaseCreator>().CreateTables();
}
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);
var post1 = blog.Posts.First(x => x.PostId == 1);
var post2 = blog.Posts.First(x => x.PostId == 2);
blog.Posts.Clear();
blog.Posts.AddRange(new List<Post>()
{
new Post()
{
PostId = 1,
Title = "title1"
},
new Post()
{
PostId = 2,
Title = "title2"
}
});
db.Entry(post1).State = EntityState.Modified;
db.Entry(post2).State = EntityState.Modified;
db.SaveChanges();
}
Console.WriteLine("Hello World!");
}
} |
@maliming Thanks; I am able to reproduce this now. Notes for team triage: The behavior is the same in 3.1; not a regression. What is happening is this:
|
Note from triage: this should throw as soon as the Deleted instances are changed back to Modified. |
EF Core version: 5.0.0-rc.2.20475.6
Database provider: Microsoft.EntityFrameworkCore.Sqlite
Target framework: net5.0
Example.csproj
Program.cs
dotnet build
dotnet run
It seems that the AcceptChanges method caused the endless loop.
efcore/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs
Line 1293 in 3199752
efcore/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs
Line 1264 in 3199752
The text was updated successfully, but these errors were encountered: