Description
File a bug
After updating EF Core from v6.0.1 to v6.0.2, two of our tests start failing. This looks like a regression in the change tracker, which no longer produces SQL for removing an element from a many-to-many relationship.
The failing tests are:
- Many-to-many relationship: https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/19f655704c91fa89f5b7561e1dd66586d9b521ee/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs#L239
- Self-referencing many-to-many relationship: https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/19f655704c91fa89f5b7561e1dd66586d9b521ee/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs#L1001
To understand what's going on: Both tests set up the database, then create an API request to remove an element from an existing many-to-many relationship. Afterwards the database contents is inspected to verify the relationship has been updated.
The logic in the API (system under test) is defined at https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/19f655704c91fa89f5b7561e1dd66586d9b521ee/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs#L460, which delegates to https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/19f655704c91fa89f5b7561e1dd66586d9b521ee/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs#L450. At a global level, the following happens: The resource service builds an EF Core query that retrieves the parent entity, along with the included subset of related resources to remove. The produced SQL for that is unchanged between EF Core versions:
-- Microsoft.EntityFrameworkCore.Database.Command: Information: Executed DbCommand (2ms) [Parameters=[@__Create_Item1_0='1'], CommandType='Text', CommandTimeout='30']
SELECT w."Id", t."Id", t."FromItemId", t."ToItemId"
FROM "WorkItems" AS w
LEFT JOIN (
SELECT w1."Id", w0."FromItemId", w0."ToItemId"
FROM "WorkItemToWorkItem" AS w0
INNER JOIN "WorkItems" AS w1 ON w0."FromItemId" = w1."Id"
WHERE w1."Id" = @__Create_Item1_0
) AS t ON w."Id" = t."ToItemId"
WHERE w."Id" = @__Create_Item1_0
ORDER BY w."Id", t."FromItemId", t."ToItemId"
Then the resource repository ensures all returned entities are tracked, marks the to-many relationship as loaded, then removes the requested related resources from the parent entity. In v6.0.1 the change tracker would "see" the removed related entities and produce SQL for that, but in v6.0.2 that no longer happens.
Result from _dbContext.ChangeTracker.DebugView.LongView
, after calling _dbContext.ChangeTracker.DetectChanges();
just before SaveChangesAsync
in v6.0.1:
WorkItem {Id: 1} Unchanged
Id: 1 PK
AssigneeId: <null> FK Unknown
Description: <null>
DueAt: <null>
GroupId: <null> FK Unknown
ParentId: <null> FK Unknown
Priority: 'Low'
Assignee: <null>
Children: []
Group: <null>
Parent: <null>
Subscribers: []
RelatedFrom: []
RelatedTo: []
Tags: []
WorkItemToWorkItem {FromItemId: 1, ToItemId: 1} Deleted
FromItemId: 1 PK FK
ToItemId: 1 PK FK
FromItem: <null>
ToItem: <null>
In v6.0.2, this returns:
WorkItem {Id: 1} Unchanged
Id: 1 PK
AssigneeId: <null> FK Unknown
Description: <null>
DueAt: <null>
GroupId: <null> FK Unknown
ParentId: <null> FK Unknown
Priority: 'Low'
Assignee: <null>
Children: []
Group: <null>
Parent: <null>
Subscribers: []
RelatedFrom: []
RelatedTo: []
Tags: []
Include provider and version information
EF Core version: v6.0.2
Database provider: PostgreSQL (tried various 6.0.x versions, no differences observed)
Target framework: .NET 6
Operating system: Windows 10 x64
IDE: Visual Studio Enterprise 2022 v17.0.5