Skip to content

Exception replacing multi-level relationship in EF7 #30135

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
iheb719 opened this issue Jan 25, 2023 · 3 comments · Fixed by #30204
Closed

Exception replacing multi-level relationship in EF7 #30135

iheb719 opened this issue Jan 25, 2023 · 3 comments · Fixed by #30204

Comments

@iheb719
Copy link

iheb719 commented Jan 25, 2023

Ask a question

I have the following model

public partial class Parent
{
    public int IdParent { get; set; }

    public virtual ICollection<FirstChild> FirstChild{ get; set; } = new List<FirstChild>();
}

public partial class FirstChild
{
    public int IdFirstChild { get; set; }

    public virtual ICollection<SecondChild> SecondChild { get; set; } = new List<SecondChild>();
}

public partial class SecondChild 
{
    public int IdSecondChild  { get; set; }

    public virtual ICollection<ThirdChild> ThirdChild{ get; set; } = new List<ThirdChild>();
}

public partial class ThirdChild
{
    public int IdThirdChild { get; set; }

    public String SomeProperty{ get; set; }
}

I update Parent with all it's relationships it this way :

var parentDB = _context.Parent.Single(x => x.IdParent == {id})
.Include(x => x.FirstChild)
.ThenInclude(x => x.SecondChild)
.ThenInclude(x => x.ThirdChild);

parentDb.FirstChild = {newCollectionValuesList}

_context.SaveChanges();

This works with EF Core 6 :

  • If in {newCollectionValuesList}, there is an element that already exists in parentDb.FirstChild (same ID), it get updated (with all its hierarchy)
  • If if does not exists, it will be added
  • If it exists but was not specified in {newCollectionValuesList}, it get deleted

When I upgraded to EF Core 7, I started to have this error :

The instance of entity type 'SecondChild' cannot be tracked because another instance with the key value '{IdSecondChild: XXXX}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached

I tried to add .AsNoTracking() in the query to resolve this, but my entities won't be updated

I don't want to loop manually through all the relationship and manually add the conditions to update the child elements

I didn't find anything related to that in What's new in EF7 nor in Breaking changes in EF7

This is a sample project with integration tests to reproduce the problem

Is this a bug ? because it works in EF6
Same result using dotnet6 and dotnet7

@ajcvickers
Copy link
Contributor

Note for triage: I am able to reproduce this. In 6.0, the existing instances are cascade-deleted before the new instances are tracked. In 7.0, the identity conflict happens before the cascade delete. Could be related to #30122.

FirstChild (Shared) {IdFirstChild: 11} Added
  IdFirstChild: 11 PK
  FirstChildName: 'firstChild1'
  IdParent: 1 FK
  IdParentNavigation: {IdParent: 1}
  SecondChild: [{IdSecondChild: 111}, {IdSecondChild: 111}]
FirstChild (Shared) {IdFirstChild: 11} Deleted
  IdFirstChild: 11 PK
  FirstChildName: 'firstChild1'
  IdParent: 1 FK
  IdParentNavigation: <null>
  SecondChild: [{IdSecondChild: 111}]
FirstChild {IdFirstChild: 12} Added
  IdFirstChild: 12 PK
  FirstChildName: 'firstChild2'
  IdParent: 1 FK
  IdParentNavigation: {IdParent: 1}
  SecondChild: []
Parent {IdParent: 1} Unchanged
  IdParent: 1 PK
  ParentName: 'parent'
  FirstChild: [{IdFirstChild: 11}, {IdFirstChild: 12}]
SecondChild (Shared) {IdSecondChild: 111} Added
  IdSecondChild: 111 PK
  IdFirstChild: 11 FK
  SecondChildName: 'secondChild1'
  IdFirstChildNavigation: {IdFirstChild: 11}
  ThirdChild: [{IdThirdChild: 1111}, {IdThirdChild: 1111}]
SecondChild (Shared) {IdSecondChild: 111} Deleted
  IdSecondChild: 111 PK
  IdFirstChild: 11 FK
  SecondChildName: 'secondChild1'
  IdFirstChildNavigation: {IdFirstChild: 11}
  ThirdChild: [{IdThirdChild: 1111}]
ThirdChild (Shared) {IdThirdChild: 1111} Added
  IdThirdChild: 1111 PK
  IdSecondChild: 111 FK
  ThirdChildName: 'thirdChild1'
  IdSecondChildNavigation: {IdSecondChild: 111}
ThirdChild (Shared) {IdThirdChild: 1111} Deleted
  IdThirdChild: 1111 PK
  IdSecondChild: 111 FK
  ThirdChildName: 'thirdChild1'
  IdSecondChildNavigation: {IdSecondChild: 111}

@ajcvickers
Copy link
Contributor

@iheb719 Workaround is to for the deletion before replacing the collection:

public void UpdateParentChild(Parent parentUpdate)
{
    var existingParent = _context.Parent.Local.FirstOrDefault(x => x.IdParent == parentUpdate.IdParent);
    existingParent?.FirstChild.Clear();
    _context.ChangeTracker.DetectChanges();
    
    var parentBd = _context.Parent
        .Include(x => x.FirstChild)
        .ThenInclude(x => x.SecondChild)
        .ThenInclude(x => x.ThirdChild)
        .Single(x => x.IdParent == parentUpdate.IdParent);

    parentBd.ParentName = parentUpdate.ParentName;
    parentBd.FirstChild = parentUpdate.FirstChild;

    _context.SaveChanges();
}

@iheb719
Copy link
Author

iheb719 commented Jan 26, 2023

Thanks @ajcvickers the workaround is working

@ajcvickers ajcvickers added this to the 7.0.x milestone Jan 28, 2023
@ajcvickers ajcvickers self-assigned this Jan 28, 2023
ajcvickers added a commit that referenced this issue Feb 3, 2023
Fixes #30122
Fixes #30135

EF7 contained some new calls to local `DetectChanges`. This resulted in re-entrance into `DetectChanges` for some types of graphs. This change prevents that.
@ajcvickers ajcvickers removed this from the 7.0.x milestone Feb 3, 2023
@ajcvickers ajcvickers reopened this Feb 3, 2023
@ajcvickers ajcvickers added this to the 7.0.x milestone Feb 9, 2023
ajcvickers added a commit that referenced this issue Feb 9, 2023
Fixes #30122
Fixes #30135

EF7 contained some new calls to local `DetectChanges`. This resulted in re-entrance into `DetectChanges` for some types of graphs. This change prevents that.
ajcvickers added a commit that referenced this issue Feb 14, 2023
Fixes #30122
Fixes #30135

EF7 contained some new calls to local `DetectChanges`. This resulted in re-entrance into `DetectChanges` for some types of graphs. This change prevents that.
@ajcvickers ajcvickers modified the milestones: 7.0.x, 7.0.4 Feb 14, 2023
@ajcvickers ajcvickers changed the title Replace multi-level relationship in Entity Framework Core 6 vs 7 Exception replacing multi-level relationship in EF7 Mar 14, 2023
@ajcvickers ajcvickers removed their assignment Aug 31, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants