使用 ThenInclude() 的结果而不是再次从 Include() 开始。 Entity Framework核心5

Using the result of ThenInclude() rather than starting at Include() again. Entity Framework Core 5

我是 EF Core 的新手,所以如果这个问题看起来很明显,请放轻松 :)

如标题所述,我想要一种方法来简化 EF 核心中的查询,这样我就不必使用 Include() 方法在查询的顶部进行重置。

这是我要处理的with/trying要摆脱的示例。

var result = await _dbContext.Zoo
                    .AsNoTracking()
                    .Include(zoo => zoo.Animal)
                        .ThenInclude(animal => animal.Cow)
                    .Include(zoo => zoo.Animal)
                        .ThenInclude(animal.Dog)
                    .Include(zoo => zoo.Animal)
                        .ThenInclude(animal.Goat)
                    .FirstOrDefaultAsync(zoo => zoo.Name = "Cool Pets");

这行得通,并且根据 提供的问题答案(我从中获得了上述示例的灵感),这就是此类查询需要处理的方式。

根据 回答的另一个问题,解决这个问题的方法是使用字符串和其他方式,例如:

dbcontext.a.Include(x => x.b)
            .ThenInclude(x => x.c)
             .Include("b.d")

-------------------------
OR
-------------------------

dbcontext.a.Include(x => x.b)
            .ThenInclude(x => x.c)
             .Include(x => x.b.d)

所以我的问题是,对于这种类型的查询,哪种方法最适合可读性和效率?

首先,您不需要受到 SO 答案的启发,因为所有这些都在 Eager Loading of Related Data section of the official EF Core documentation, and in particular with lot of examples in Including multiple levels 小节中有很好的记录(即使后来添加的字符串重载不包括在那里) .

但要回答你的具体问题。

Using the result of ThenInclude() rather than starting at Include() again

这是不可能的,因为以这种方式“重新启动”包含路径是设计使然,通常是 Include -> ThenInclude -> ThenInclude .. . 模式有效

As the title mentions, I would like a way to simplify queries in EF core, so that I don't have to reset at the top of my query with the Include() method

So my question is, which approach to this type of query, if either, is best for readability and efficiency?

可读性是主观的,因此取决于您。效率 - 这无关紧要(因此不需要“简化”或“优化”),因为所有这些方法都是 等效的 并产生一个相同的查询和结果(如果需要优化,它是您包含的 很多 事物的数量,而不是您将它们包含在查询结果中的方式。

你需要意识到的是

(1) 所有这些方法都是表达 include paths 的替代方法。 ThenInclude 专门用于解决包含集合元素的 属性 的 C# 语法问题,即虽然您可以编写 Include(a => a.B.C) 以防 B 是引用类型导航,但您可以不要写 Include(a => a.Bs.C),其中 Bs 是具有 属性 CB 的集合。在那种情况下,您可以使用 string 重载 Include("Bs.C"),但字符串的一般问题是它们容易出错,并且您会失去表达式提供的类型安全性。 “经典”Entity Framework (EF6) 解决了集合包含标准 LINQ Select 的语法问题,即 Include(a => a.Bs.Select(b => b.C)),但它看起来有点不自然,因此 EF Core 引入了“更直观”ThenInclude.

(2) 生成的查询中仅包含唯一路径。也就是说,重复 Include(zoo => zoo.Animal) 并不意味着它会被多次包含。不,它只会包含一次。与子路径相同,您必须重复才能 ThenInclude 另一个 属性.

(3)包含路径自动包含所有级别,即

Include(a => a.B).ThenInclude(b => b.C).ThenInclude(c => c.D)

Include(a => a.B.C.D)

照样做。


话虽如此,针对特定场景使用哪种方法只是个人品味的问题。我个人尽可能使用紧凑的表达式形式(基本上直到你碰到一个集合),否则 ThenInclude ,并避免 string 由于明显的维护(不是功能或效率)缺点而过载,即使后来最终可以用内插字符串和 nameof 运算符来解决。