[英]How to query only a small part from a navigation property (without including all data in that property)?
I have this small scenario: 我有一个小场景:
var user = await dbContext.Users
.Include(u => u.Posts)
.SingleOrDefaultAsync(u => u.Id == userId);
return user
.SelectMany(u => u.Posts)
.Skip(someStartIndex)
.Take(someCount);
The problem with this scenario is that skip
and take
happen in the memory (after loading a lot of posts from the database into the memory because of issuing Include
). 这个方案的问题是,
skip
和take
的记忆发生(从数据库加载很多帖子进入,因为发出的内存后Include
)。 I just want to query small amount of those posts from the database in the first query where I get the user (instead of including the whole posts). 我只想在获取用户的第一个查询中从数据库中查询少量的帖子(而不是包括整个帖子)。 In other words, I want somehow to query small amount of the included data, instead of including them all.
换句话说,我想以某种方式查询少量的包含数据,而不是全部包含它们。
How can I achieve that? 我该如何实现?
PS: In my real code the Posts are not directly under User, but in multiple sub-properties. PS:在我的真实代码中,帖子不是直接位于用户下,而是位于多个子属性中。 I just omitted that to keep the code simple, as the idea of how can I include only a part should still the same.
我只是为了使代码简单而省略了它,因为我如何只包含一部分的想法应该仍然相同。
My real code, to have a better understanding of the situation: 我的真实代码是为了对情况有更好的了解:
public async Task<IEnumerable<Post>> GetPostsFromFollowsAsync(Guid userId, int count, int startIndex)
{
//TODO rewrite this ugly query!!!
var user = await dbContext.Users
.Include(u => u.UserFollowing)
.ThenInclude(uf => uf.FollowingUser)
.ThenInclude(u => u.Posts)
.ThenInclude(p => p.Writer)
.ThenInclude(u => u.Profile)
.Include(u => u.UserFollowing)
.ThenInclude(uf => uf.FollowingUser)
.ThenInclude(u => u.Posts)
.ThenInclude(p => p.PostLikes)
.Include(u => u.UserFollowing)
.ThenInclude(uf => uf.FollowingUser)
.ThenInclude(u => u.Posts).
ThenInclude(p => p.PostCategories)
.ThenInclude(pc => pc.Category)
.Include(u => u.UserFollowing)
.ThenInclude(uf => uf.FollowingUser)
.ThenInclude(u => u.Posts)
.ThenInclude(p => p.Comments)
.SingleOrDefaultAsync(u => u.Id == userId);
return user
.UserFollowing
.Select(uf => uf.FollowingUser)
.SelectMany(u => u.Posts)
.Skip(startIndex)
.Take(count);
}
In this specific scenario you can start the query from Posts
and use the inverse navigation property for filtering / additional includes: 在这种特定情况下,您可以从“
Posts
开始查询,并使用反向导航属性进行过滤/其他包括:
var userPosts = await dbContext.Posts
.Include(p => p.User)
// other includes ...
.Where(p => p.User.Id == userId)
.Skip(someStartIndex)
.Take(someCount)
.ToListAsync();
This way the Skip
/ Take
will happen server side. 这样,“
Skip
/ Take
将发生在服务器端。
Update: The actual structure doesn't change the concept. 更新:实际的结构不会改变概念。 You just need to navigate backwards and change the user Id filter to
Any
due to many-to-many relationship: 由于多对多关系,您只需要向后导航并将用户ID过滤器更改为
Any
:
return await dbContext.Posts
.Include(p => p.Writer) // Parent info
.ThenInclude(u => u.UserFollowers)
.ThenInclude(uf => uf.FollowerUser)
.Include(p => p.Writer) // Child info
.ThenInclude(u => u.Profile)
.Include(p => p.PostLikes)
.Include(p => p.PostCategories)
.ThenInclude(pc => pc.Category)
.Include(p => p.Comments)
.Where(p => p.Writer.UserFollowers.Any(uf => uf.FollowerUser.Id == userId))
.Skip(startIndex)
.Take(count)
.ToListAsync();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.