-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Description
By reading this post relationship-changes. In many-to-many relationships, I consider when removing join entities PostTags from post.PostTags the removed entity will also disapper from tag.PostTags
If query tags before ctx.ChangeTracker.DetectChanges() it performs as expected.
However call ctx.ChangeTracker.DetectChanges() before query tags, the tag{id=2}'s navigation property PostTags still has {PostId: 1, TagId: 2} which state is deleted.
It dosen't disapper although I call ctx.ChangeTracker.DetectChanges() again
how to make DetectChanges has consistent result, no matter what order of invocation.
Entitis
using System.Collections.Generic;
namespace Web.Tests
{
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public IList<PostTag> PostTags { get; } = new List<PostTag>(); // Collection navigation
}
public class Tag
{
public int Id { get; set; }
public string Text { get; set; }
public IList<PostTag> PostTags { get; } = new List<PostTag>(); // Collection navigation
}
public class PostTag
{
public int PostId { get; set; } // First part of composite PK; FK to Post
public int TagId { get; set; } // Second part of composite PK; FK to Tag
public Post Post { get; set; } // Reference navigation
public Tag Tag { get; set; } // Reference navigation
}
}using Microsoft.EntityFrameworkCore;
namespace Web.Tests
{
public class BlogContext : DbContext
{
public BlogContext(DbContextOptions<BlogContext> options) : base(options) { }
public DbSet<Post> Posts { get; set; }
public DbSet<Tag> Tags { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>()
.HasData(
new Post { Id = 1, Title = "How to use vs?", Content = "blababa" }
);
modelBuilder.Entity<Tag>()
.HasData(
new Tag { Id = 1, Text = ".NET" },
new Tag { Id = 2, Text = "C#" }
);
modelBuilder.Entity<PostTag>()
.HasKey(x => new { x.PostId, x.TagId });
modelBuilder.Entity<PostTag>()
.HasOne(x => x.Post)
.WithMany(x => x.PostTags);
modelBuilder.Entity<PostTag>()
.HasOne(x => x.Tag)
.WithMany(x => x.PostTags);
modelBuilder.Entity<PostTag>()
.HasData(
new PostTag { PostId = 1, TagId = 1 },
new PostTag { PostId = 1, TagId = 2 }
);
base.OnModelCreating(modelBuilder);
}
}
}UnitTest1.cs
[Fact]
public void Test1()
{
var ctx = CreateContext();
var post = ctx.Posts.Include(x => x.PostTags).SingleOrDefault(x => x.Id == 1);
if (post != null)
{
post.PostTags.RemoveAt(1);
}
ctx.ChangeTracker.DetectChanges();
Debug.WriteLine(ctx.ChangeTracker.DebugView.LongView);
var tag = ctx.Tags.Include(x => x.PostTags).ToList();
Debug.WriteLine(ctx.ChangeTracker.DebugView.LongView);
ctx.ChangeTracker.DetectChanges();
Debug.WriteLine(ctx.ChangeTracker.DebugView.LongView);
ctx.SaveChanges();
} Post {Id: 1} Unchanged
Id: 1 PK
Content: 'blababa'
Title: 'How to use vs?'
PostTags: [{PostId: 1, TagId: 1}]
PostTag {PostId: 1, TagId: 1} Unchanged
PostId: 1 PK FK
TagId: 1 PK FK
Post: {Id: 1}
Tag: <null>
PostTag {PostId: 1, TagId: 2} Deleted
PostId: 1 PK FK
TagId: 2 PK FK
Post: <null>
Tag: <null>
Post {Id: 1} Unchanged
Id: 1 PK
Content: 'blababa'
Title: 'How to use vs?'
PostTags: [{PostId: 1, TagId: 1}]
PostTag {PostId: 1, TagId: 1} Unchanged
PostId: 1 PK FK
TagId: 1 PK FK
Post: {Id: 1}
Tag: {Id: 1}
PostTag {PostId: 1, TagId: 2} Deleted
PostId: 1 PK FK
TagId: 2 PK FK
Post: <null>
Tag: {Id: 2}
Tag {Id: 1} Unchanged
Id: 1 PK
Text: '.NET'
PostTags: [{PostId: 1, TagId: 1}]
Tag {Id: 2} Unchanged
Id: 2 PK
Text: 'C#'
PostTags: [{PostId: 1, TagId: 2}]
Post {Id: 1} Unchanged
Id: 1 PK
Content: 'blababa'
Title: 'How to use vs?'
PostTags: [{PostId: 1, TagId: 1}]
PostTag {PostId: 1, TagId: 1} Unchanged
PostId: 1 PK FK
TagId: 1 PK FK
Post: {Id: 1}
Tag: {Id: 1}
PostTag {PostId: 1, TagId: 2} Deleted
PostId: 1 PK FK
TagId: 2 PK FK
Post: <null>
Tag: {Id: 2}
Tag {Id: 1} Unchanged
Id: 1 PK
Text: '.NET'
PostTags: [{PostId: 1, TagId: 1}]
Tag {Id: 2} Unchanged
Id: 2 PK
Text: 'C#'
PostTags: [{PostId: 1, TagId: 2}]
Include provider and version information
EF Core version:5.0.12
Database provider: Pomelo.EntityFrameworkCore.MySql
Target framework:NET 5.0
Operating system:
IDE: vscode latest