Skip to content

Add a SetLoaded method with a lambda callback that allows the state of entities in the collection to be set. #27436

Open
@bart-degreed

Description

@bart-degreed

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:

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions