One-to-many add/remove fails foreign key constraint

Open
#25,436 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Stale
Tech stack
csharp, mariadb, sqlite
Domain
database

Research direction

Start at the SaveChanges() entry point and reproduce the supplied Blog/Post model with the Posts.Clear() call using the stated SQLite and MariaDB providers. Trace change tracking and update ordering to determine why an insert remains, then verify that SaveChanges() completes without a foreign-key exception or database queries.

Written by the indexing model from the issue text.

Description

area-change-tracking customer-reported

The following program raises a foreign key constraint failed exception on SaveChanges().
I would expect it to work and SaveChanges() should execute no queries.
I checked with Sqlite and MariaDb.

Example
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;

Blog blog = new Blog
{
    Posts = new List<Post>
    {
        new Post()
    }
};

using var dbContext = new AppDbContext();
dbContext.Database.EnsureDeleted();
dbContext.Database.EnsureCreated();

dbContext.Blogs.Add(blog);
blog.Posts.Clear(); // <- without this line, everything works as expected
dbContext.Blogs.Remove(blog);

dbContext.SaveChanges(); // <- exception happens here

class AppDbContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

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

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder.UseSqlite("data source=test.db");
}

class Blog
{
    public int Id { get; set; }

    public IList<Post> Posts { get; set; }
}

class Post
{
    public int Id { get; set; }

    public int BlogId { get; set; }

    public Blog Blog { get; set; }
}
Logs
fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
      Failed executing DbCommand (4ms) [Parameters=[@p0='-2147482647' (DbType = String)], CommandType='Text', CommandTimeout='30']
      INSERT INTO "Posts" ("BlogId")
      VALUES (@p0);
      SELECT "Id"
      FROM "Posts"
      WHERE changes() = 1 AND "rowid" = last_insert_rowid();
fail: Microsoft.EntityFrameworkCore.Update[10000]
      An exception occurred in the database while saving changes for context type 'AppDbContext'.
      Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
       ---> Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 19: 'FOREIGN KEY constraint failed'.
         at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
         at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
         at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)
         at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior)
         at System.Data.Common.DbCommand.ExecuteReader()
         at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
         at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
         --- End of inner exception stack trace ---
         at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
         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(DbContext _, Boolean acceptAllChangesOnSuccess)
         at Microsoft.EntityFrameworkCore.Storage.NonRetryingExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
Environment

EF Core version: 5.0.8
Database provider: Microsoft.EntityFrameworkCore.Sqlite and Pomelo.EntityFrameworkCore.MySql
Target framework: .NET 5.0
Operating system: Win 10
IDE: Visual Studio 2019

Dominant language
C#
Stars
14.8k
Forks
3.4k
Avg merge
2d 5h
Merged PRs (30d)
134

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from dotnet/efcore

All issues in dotnet/efcore

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.