Skip to content

FK dependency ordering wrong when replacing an inline owned entity #36059

@bachratyg

Description

@bachratyg

Bug description

See gist below.
Document has an optional owned File
File has a required reference to Content.
When File is replaced and the original Content is removed an exception is thrown on SaveChanges.

Actual sql:

DELETE FROM [Contents]
OUTPUT 1
WHERE [Id] = @p0;
INSERT INTO [Contents] ([Id], [Data])
VALUES (@p1, @p2);
UPDATE [Documents] SET [File_ContentId] = @p3, [File_Id] = @p4, [File_Name] = @p5
OUTPUT 1
WHERE [Id] = @p6;

Expected sql:

INSERT INTO [Contents] ([Id], [Data])
VALUES (@p1, @p2);
UPDATE [Documents] SET [File_ContentId] = @p3, [File_Id] = @p4, [File_Name] = @p5
OUTPUT 1
WHERE [Id] = @p6;
DELETE FROM [Contents]
OUTPUT 1
WHERE [Id] = @p0;

This works fine if the File entity is not owned (remove the [Owned] attribute and uncomment the indicated line in the gist to test this)

Also reproduces on EFC 8.0.11 and .NET 8

Your code

https://gist.github.com/bachratyg/d073cbb7c47a494939f2aa5c419992c2

Stack traces

Stack trace

      An exception occurred in the database while saving changes for context type 'AppDb'.
      Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
       ---> Microsoft.Data.SqlClient.SqlException (0x80131904): The DELETE statement conflicted with the REFERENCE constraint "FK_Documents_Contents_File_ContentId". The conflict occurred in database "Test", table "dbo.Documents", column 'File_ContentId'.
         at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
         at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
         at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
         at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
         at Microsoft.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
         at Microsoft.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
         at Microsoft.Data.SqlClient.SqlDataReader.Read()
         at Microsoft.EntityFrameworkCore.Storage.RelationalDataReader.Read()
         at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeResultSetWithRowsAffectedOnly(Int32 commandIndex, RelationalDataReader reader)
         at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.Consume(RelationalDataReader reader)
      ClientConnectionId:62ce916b-d921-4135-87f3-892b604a5a45
      Error Number:547,State:0,Class:16
         --- End of inner exception stack trace ---
         at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.Consume(RelationalDataReader reader)
         at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
         at Microsoft.EntityFrameworkCore.SqlServer.Update.Internal.SqlServerModificationCommandBatch.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(StateManager stateManager, Boolean acceptAllChangesOnSuccess)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<>c.<SaveChanges>b__112_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)

EF Core version

9.0.4

Database provider

Microsoft.EntityFrameworkCore.SqlServer

Target framework

.NET 9.0

Operating system

Windows 10

IDE

Visual Studio 2022 17.13

Metadata

Metadata

Assignees

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions