Reputation: 796
After upgrading my project to EF Core 6, I have a strange behaviour:
I have two classes in my dbcontext with a many-to-many relation - like this:
public class SiteImage
{
public int siteImageId { get; set; }
public string siteImageUrl { get; set; }
...
public ICollection<SiteImageCategory> categories { get; set; }
}
public class SiteImageCategory
{
public int siteImageCategoryId { get; set; }
public string name { get; set; }
public ICollection<SiteImage> images { get; set; }
}
They are mapped to tables in DBContext
public DbSet<SiteImage> images { get; set; }
public DbSet<SiteImageCategory> categories { get; set; }
If I want to retrieve all images with this code:
var images = await _context.images.ToListAsync();
I have get the list of images with all categories = null and and that's what I expected.
But if I want to include categories using eager loading, like this:
var images = await _context.images
.Include(x => x.categories)
.ToListAsync();
I get the list with categories, but any category includes all related images, with a related categories in an infinite loop (stopped by ReferenceHandler.IgnoreCycles
setting).
I would have expected the code to stop at the category level, according to include statement.
What am I doing wrong?
Thanks
Upvotes: 0
Views: 1274
Reputation: 74605
ReferenceHandler.IgnoreCycles
This is nothing to do with EF nor anything that it did wrong. You're serializing your db entity graph, which you should avoid doing because it's a bidirectionally linked graph.
An image X has categories Y, Z etc and those categories have images, one of which is image X, which ..
has categories Y, Z etc and those categories have images, one of which is image X, which ..
has categories Y, Z etc and those categories have images, one of which is image X, which ..
has categories Y, Z etc and those categories have images, one of which is image X, which ..
And so on.
As the serializer serializes the graph it will travel these paths and go into a cycle, only stopping if it can keep track of everything it's ever seen before
If you don't want to rely on that then there are other options:
I'd say it's probably most common to take the latter approach, and don't serialize db entities
Upvotes: 0
Reputation: 89091
I would have expected to stop at the category level, according to include stantment.
It did. However when each SiteImageCategory is loaded, if its SiteImage is already in the change tracker, the relationship will be "fixed up". So if you load all the SiteImages you will already have each SiteImageCategory's SiteImages in the Change Tracker, and the inverse navigation property collection will be populated.
Upvotes: 4