Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Many To Many Exception when adding and removing same entity #26779

Closed
DanielBlazevic opened this issue Nov 22, 2021 · 3 comments · Fixed by #26853 or #26892
Closed

Many To Many Exception when adding and removing same entity #26779

DanielBlazevic opened this issue Nov 22, 2021 · 3 comments · Fixed by #26853 or #26892
Labels
area-change-tracking closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported Servicing-approved type-bug
Milestone

Comments

@DanielBlazevic
Copy link

DanielBlazevic commented Nov 22, 2021

File a bug

Not sure if this is bug, but I noticed different behavior when using many-to-many feature in "old" and "new" way.

If I configure many-to-many in "old" way with third model defined (Post, Tag, PostTag) and test adding and removing same PostTag, everything works as expected. Nothing is changed and no saves are necessary.

But if I do it "new" way without third model defined (only Post and Tag) and test adding Tag to Post and then removing the same Tag from same Post I get exception when trying to save changes, because context tries to delete PostTag entity which does not exists in database.

Include your code

Example code can be found in https://github.com/DanielBlazevic/EFCoreTest

    static void SeedData()
    {
        var ctx = new Context();

        ctx.Database.EnsureDeleted();
        ctx.Database.EnsureCreated();

        var post = new Post() { Title = "Post 1" };

        var tag = new Tag() { Text = "Tag 1" };

        ctx.Add(post);
        ctx.Add(tag);

        ctx.SaveChanges();
    }

"Old" way:

    static void Main(string[] args)
    {
        SeedData();

        var ctx = new Context();

        var post = ctx.Posts.First();

        var tag = ctx.Tags.First();

        var postTag = new PostTag() { Post = post, Tag = tag };

        post.PostTags.Add(postTag);

        ctx.ChangeTracker.DetectChanges();

        Console.WriteLine(ctx.ChangeTracker.DebugView.LongView);

        post.PostTags.Remove(postTag);

        ctx.ChangeTracker.DetectChanges();

        Console.WriteLine(ctx.ChangeTracker.DebugView.LongView);

        ctx.SaveChanges(); // <- Nothing to save, no exception
    }

"New" way:

    static void Main(string[] args)
    {
        SeedData();

        var ctx = new Context();

        var post = ctx.Posts.First();

        var tag = ctx.Tags.First();

        post.Tags.Add(tag);

        ctx.ChangeTracker.DetectChanges();

        Console.WriteLine(ctx.ChangeTracker.DebugView.LongView);

        post.Tags.Remove(tag);

        ctx.ChangeTracker.DetectChanges();

        Console.WriteLine(ctx.ChangeTracker.DebugView.LongView);

        ctx.SaveChanges(); // <- Tries to delete PostTag entity, Exception here
    }

Exception

Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: 'The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.'

Include provider and version information

EF Core version: 6
Database provider: Microsoft.EntityFrameworkCore.SqlServer / Microsoft.EntityFrameworkCore.Sqlite
Target framework: .NET 6.0
Operating system: Windows 10 x64
IDE: Visual Studio 2022

@BewaAutomatisierung-RD
Copy link

Try Including Tags when you load your post:
var post = ctx.Posts.Include(p => p.Tags).First();

@DanielBlazevic
Copy link
Author

Already tried that, same results.

@ajcvickers
Copy link
Member

Note for triage: looks like a bug, but may be complicated by join entity synthesis.

ajcvickers added a commit that referenced this issue Nov 30, 2021
Fixes #26779

Also fix related issue where fixup to the join entity was not happening when it was synthesized from navigation change.
@ajcvickers ajcvickers self-assigned this Nov 30, 2021
@ajcvickers ajcvickers added this to the 6.0.x milestone Dec 1, 2021
ajcvickers added a commit that referenced this issue Dec 3, 2021
Fixes #26779

**Description**

When a many-to-many relationship is created and then removed, the state of the join entity that represents this relationship is incorrectly changed to `Deleted`. This results in an attempt to delete a row in the database that does not exist.

**Customer impact**

Exception thrown when calling SaveChanges after adding and then removing a new many-to-many relationships.

This is a fairly fundamental error. What is not clear is why this was not reported before now, since the behavior existed in 5.0. It's possible people didn't realize it was a bug and having been manually detaching the join entity to make this scenario work.

**How found**

Customer reported on 6.0.

**Regression**

This is not a regression; the same behavior existing in 5.0. However, we believe that it is a fundamental behavior that should work, hence we believe we should patch in 6.0.

**Testing**

Added a range of new tests for this and related scenarios with different types of many-to-many relationships.

**Risk**

Low; the change is very simple, and is also quirked.
@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Dec 5, 2021
ajcvickers added a commit that referenced this issue Dec 5, 2021
…hip is created

Fixes #26779

Also cleanup of delay-fixup/suspended detection logic, and tests for #26074.
ajcvickers added a commit that referenced this issue Dec 6, 2021
…hip is created

Fixes #26779

Also cleanup of delay-fixup/suspended detection logic, and tests for #26074.
ajcvickers added a commit that referenced this issue Dec 8, 2021
…hip is created

Fixes #26779

Also cleanup of delay-fixup/suspended detection logic, and tests for #26074.
ajcvickers added a commit that referenced this issue Dec 9, 2021
…hip is created

Fixes #26779

Also cleanup of delay-fixup/suspended detection logic, and tests for #26074.
@ajcvickers ajcvickers reopened this Dec 9, 2021
@ajcvickers ajcvickers modified the milestones: 6.0.x, 6.0.2 Dec 14, 2021
@ajcvickers ajcvickers removed their assignment Aug 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-change-tracking closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported Servicing-approved type-bug
Projects
None yet
3 participants