Preventing automatic population of circular navigation properties in Entity Framework

只愿长相守 提交于 2019-12-23 02:36:29

问题


I have a problem when retrieving entities which have a circular reference. My entity navigation properties are not lazy loaded, so I would expect them to return null unless specifically included in a query, however I've found that when there is a circular reference between two entities this isn't the case and instead a recursive hierarchy is returned.

For example, let's say we have two entities UserEntity and PostEntity. A UserEntity may have many posts, but a post must only have a single UserEntity. So, the configuration is as follows:

// UserEntity configuration
HasMany(u => u.Posts)
  .WithRequired(p => p.User);

If I query the database for either a UserEntity or a PostEntity without using Include() on the respective Posts or User navigation properties, the navigation properties are null as expected.

However, if I query for a UserEntity and include its PostEntitys, an circular hierarchy is returned, even though I never requested that the PostEntity.User navigation property be populated:

using (var db = new MyDbContext())
{
  var user = await db.Users
    .Include(u => u.Posts)
    .SingleOrDefaultAsync(u => u.ID == 0);

  // The [UserEntity] contains a list of [PostEntitiy]s
  //   each with the [UserEntity] each with a list of [PostEntitiy]s...
  //     and so on.
}

This isn't too much trouble, but when a list of PostEntitys are retrieved and their UserEntitys are included things get very weird:

using (var db = new MyDbContext())
{
  var posts = await db.Posts
    .Include(p => p.User)
    .SingleOrDefaultAsync(p => p.ID == 0);

  // This throws a [System.InvalidOperationException]:
  // "Sequence contains more than one element"
  // How can this be? The ID is unique.

  var posts = await db.Posts
    .Include(p => p.User)
    .Where(p => p.ID == 0)
    .ToListAsync();

  // This returns several copies of the PostEntity
  //   which should be unique in the database. Is
  //   this a side effect of the circular reference?
}

Obviously getting rid of the circular reference would fix this, but there are several reasons why keeping it is beneficial, if possible. Why is EntityFramework returning this circular hierarchy despite only a single, one-way relationship being requested with Include(), and why is this resulting in several PostEntitys being returned when their UserEntitys are included?


回答1:


You could try projecting your entities into DTOs to work around this. Use projection into some type that does not have such references and avoid the exception.

In other words, pick up just the properties that you need from the EF model, not adding fields which are nested complex types that also have properties that point back to the same object and thus create circular references

using (var db = new MyDbContext())
{
    var posts = db.Posts
        .Include(p => p.User)
        .Where(p => p.ID == 0)
        .Select(p => new PostsDTO
        {
            Name = p.Name,
            Username = p.User.Username
        });
}


来源:https://stackoverflow.com/questions/34801414/preventing-automatic-population-of-circular-navigation-properties-in-entity-fram

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!