c# - 防止 Entity Framework 中循环导航属性的自动填充

标签 c# entity-framework linq circular-reference

我在检索具有循环引用的实体时遇到问题。我的实体导航属性不是延迟加载的,因此我希望它们返回 null,除非特别包含在查询中,但是我发现当两个实体之间存在循环引用时,情况并非如此,而是递归层次结构已返回。

例如,假设我们有两个实体 UserEntityPostEntity 。一个UserEntity可以有很多帖子,但一个帖子只能有一个 UserEntity 。所以,配置如下:

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

如果我在数据库中查询 UserEntityPostEntity不使用Include()分别在PostsUser导航属性,导航属性按预期为 null。

但是,如果我查询 UserEntity并包括其 PostEntity s,返回一个循环层次结构,即使我从未要求 PostEntity.User填充导航属性:

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.
}

这并不是太麻烦,但是当列表 PostEntity 时s 被检索并且它们 UserEntity包含在内的事情变得非常奇怪:

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?
}

显然,摆脱循环引用可以解决这个问题,但有几个原因可以解释为什么保留它是有益的(如果可能的话)。 尽管 Include() 仅请求一个单向关系,但为什么 EntityFramework 仍返回此循环层次结构,以及为什么这会导致几个 PostEntity当他们的UserEntity时被返回包括在内吗?

最佳答案

您可以尝试将实体投影到 DTO 中来解决此问题。使用projection转换为没有此类引用的某种类型并避免异常。

换句话说,只从 EF 模型中选取所需的属性,而不是添加嵌套复杂类型的字段,这些复杂类型也具有指向同一对象的属性,从而创建循环引用

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
        });
}

关于c# - 防止 Entity Framework 中循环导航属性的自动填充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34801414/

相关文章:

c# - EF6 : Configure complex mapping for entities (code first)

entity-framework - EF Core 中的一对一关系(无法确定一对一关系的子/依赖方)

c# - 将列表分解为一组索引列表

c# - 迭代 Linq 表达式结果与首先将其分配给变量是否相同?

c# - 如何判断默认打印机何时更改?

c# - 打印服务器 - 想要捕获打印命令

C# 列表框 : Display custom items in listbox

entity-framework - 为什么在 EF Code First 中经常无法解释地使用部分修饰符?

sql-server - 添加迁移和更新数据库命令未找到 Visual Studio 2015

Linq:运算符不理解表达式类型谓词的查询语法