EF Side Effect
Tuesday, May 19, 2026
I happened to find a side effect of Entity Framework that caused a confusion. Thanks to Claude Sonnet (AI) that I managed to understand what's going on.
It started with the following example structure. Let say:
Blog (ID: 1)
- Post 1 (ID: 2)
- Post 2 (ID: 3)
I need to copy the structure as a new structure, but without Post 2, so the first step is set the ID to be 0. That will trigger EF to treat them as new object and thus will perform an insert.
Blog (ID: 0)
- Post 1 (ID: 0)
- Post 2 (ID: 0)
Then, I removed Post 2 and perform a SaveAsync(), so it is expected to be:
Blog (ID: 1)
- Post 1 (ID: 2)
- Post 2 (ID: 3)
Blog (ID: 5)
- Post 1 (ID: 6)
Instead, what happened was, it became the following. Noticed that the original Post 2 became the child of the new Blog.
Blog (ID: 1)
- Post 1 (ID: 2)
Blog (ID: 5)
- Post 1 (ID: 6)
- Post 2 (ID: 3)
What happened was, during setting ID to 0, EF tracks Post 2 and found out that it has changed. Remove Post 2 from memory doesn't detach it (an entity) from the tracker. And thus, in EF, it thought Post 2 needs to be updated instead.
class Blog
{
List<Post> Posts { get; set; }
}
blog.Posts.Remove(post2); // This will not detach it from tracker.
The solution is to reset the ID after removal. So, first we perform removal, so EF doesn't think Post 2 has changed and then reset the ID.
Remove Post 2 first:
Blog (ID: 1)
- Post 1 (ID: 2)
Then reset the ID:
Blog (ID: 0)
- Post 1 (ID: 0)
That way, EF will insert the blog as new entity along with Post 1, but leaving Post 2 alone since in the tracker, it hasn't changed.