嗨,我是LINQ、EF和Im的新手,我试图理解为什么下面的代码不返回嵌套实体,即使我使用include显式地加载它们
var x = await _context.AuthorBooks.Where(ub => ub.AuthorId == authorId)
.Include(ub => ub.Book)
.ThenInclude (b=> b.Chapters)
.Select(ub => ub.Book).ToListAsync();AuthorBooks是链接对象,我可以在其中应用过滤器,只从特定作者中选择书籍。
我试图为给定的作者选择带章节的所有图书的列表,但是上面的代码返回书籍列表,但是没有嵌套的章节。
有什么帮助吗?
发布于 2018-05-14 14:49:19
解释
你在触及EF中确实存在的一种行为。
问题在于EF如何处理数据加载。默认情况下,它加载对象的所有标量属性,但不加载导航属性。
Include通过告诉EF还包括指定的导航属性(以及它的所有标量属性)来影响这种行为。
但是我们到了Select。当您使用它时,本质上是给出要检索的固定的列列表。EF将仅限于您提到的字段。
var x1 = _context.Books.Select(b => b.Name).ToList();这将导致只检索单个列的查询。
var x2 = _context.AuthorBooks.Select(ab => ab.Book).ToList();由于您指的是导航属性(没有在其中指定任何特定的标量属性),EF使用它的默认行为加载导航属性的所有标量属性。查询将获取X列(其中X是Book中标量属性的数量)。
var x3 = _context.AuthorBooks.Select(ab => ab.Book.Name).ToList();这将再次导致只检索单个列的查询,因为您引用了特定的标量属性。
解决方案
Select**.** 1.反转查询,因此不需要
这对你目前的情况是有效的,但并不适用于所有的情况。
var x = await _context.Books
.Include(b=> b.Chapters)
.Where(b => b.AuthorBooks.Any(ab => ab.AuthorId == authorId))
.ToListAsync();Select 2.在检索数据后执行.
对于您的情况,这将导致加载AuthorBook实体,这是不理想的。这是可行的,但您获取的数据比您需要的多。但是,在1.不是可行方法的情况下,这种方法更好
var x = await _context.AuthorBooks
.Include(ub => ub.Book)
.ThenInclude(b=> b.Chapters)
.Where(ub => ub.AuthorId == authorId)
//Fetch the data
.ToList()
//Now transform the result
.Select(ub => ub.Book)
.ToListAsync()Select 3.显式地将想要的数据添加到
var x = await _context.AuthorBooks.Where(ub => ub.AuthorId == authorId)
.Select(ub => new {
Book = ub.Book,
Chapters = ub.Book.Chapters
});Include语句的。因为您正在显式地告诉EF它应该检索什么,所以它不需要依赖于关于应该加载哪些导航属性的隐式说明。4.在Include Select**.**之后添加
由于NetMage在评论中首先提到了它,所以可以使用Credits。
var x = await _context.AuthorBooks.Where(ub => ub.AuthorId == authorId)
.Select(ub => ub.Book)
.Include(b => b.Chapters)
.ToListAsync();请注意,前面的包含并不是必需的,因为后续的Select无论如何都会重写它们。
在我看来,选项4是最干净的解决方案。
但是,如果只对导航属性的子集感兴趣,则选项3更好。例如,如果您只想获得具有最小字数的章节:
var x = await _context.AuthorBooks.Where(ub => ub.AuthorId == authorId)
.Select(ub => new {
Book = ub.Book,
Chapters = ub.Book.Chapters.Where(c => c.WordCount > 1000)
});Include加载所有相关属性。显式Select为您提供了加载相关属性子集的选项,从而降低了要传输的数据量。
https://stackoverflow.com/questions/50292776
复制相似问题