基本上我要做的是查询父实体的子集合。根据EF Core文档,我可以使用Include
和ThenInclude
方法来执行此操作(https://docs.microsoft.com/en-us/ef/core/querying/related-data)。所以,我在我的存储库中有这个代码来获取我想要的数据:
public object GetMatchupByVideoId(int id)
{
var videoMatchup = _DBContext.Matchups
.Where(m => m.VideoID == id)
.Include(m => m.Players).ThenInclude(p => p.Character)
.Include(m => m.Players).ThenInclude(p => p.User);
return videoMatchup;
}
此代码主要查找与传递的Matchups
匹配的id
实体。然后它出去并包含Players
集合,它是模型上的导航属性。返回的数据如下所示:
[
{
"id": 1,
"players": [
{
"id": 1,
"user": {
"id": 1,
"displayName": "Player 1"
},
"character": {
"id": 40,
"name": "Superman"
},
"outcome": 0
},
{
"id": 2,
"user": {
"id": 2,
"displayName": "Player 2"
},
"character": {
"id": 43,
"name": "Batman"
},
"outcome": 1
}
]
}
]
这一切都很好,但它给了我比我真正感兴趣的更多的数据。例如,我宁愿让我的user
属性只有displayName
的值属性。除此之外,这是我想要的数据结构,我只是想改变一些属性。
寻找答案我发现有些人建议使用SelectMany
。所以,当我重新安排我的代码时:
public object GetMatchupByVideoId(int id)
{
var videoMatchup = _DBContext.Matchups
.Where(m => m.VideoID == id)
.SelectMany(m => m.Players, (parent, child) => new { parent, child })
.Select(pc => new {
players = pc.child
});
return videoMatchup;
}
返回的数据如下所示:
[
{
"players": {
"id": 1,
"user": null,
"character": null,
"outcome": 0
}
},
{
"players": {
"id": 2,
"user": null,
"character": null,
"outcome": 1
}
}
]
这有一些缺点。第一个是没有相关数据被加载,它们是players
的两个独立对象,只要它们应该在一个集合中。
所以,我有几个问题,我认为这些问题都与同一个答案有关:
Include
的情况下查询子数据?我觉得很难相信这是唯一的方法。SelectMany
方法将对象与一个列表进行协调,就像返回的第一个数据结构一样?答案 0 :(得分:3)
我提出的所有问题都与我怀疑的单一答案有关。在搜索并完成它之后,您可以通过以下方式完成此任务:
public object GetMatchupByVideoId(int id)
{
var videoMatchup = _DBContext.Matchups
.Where(m => m.VideoID == id)
.Select(m => new {
ID = m.VideoID,
Players = m.Players.Select(p => new {
ID = p.PlayerID,
User = p.User,
Character = p.Character,
Outcome = p.Outcome
})
});
return videoMatchup;
}
SelectMany
不是正确的做法。你想要的是使用Select
并使用你的子列表中的投影。这回答了我提出的以下问题:
只需使用Select
方法将您的子列表投影到导航属性中。
SelectMany
方法将对象与一个列表进行协调,就像返回的第一个数据结构一样? 在这种情况下,您不会因为SelectMany
用于展平列表列表。
与第一个答案相同。
与第一个答案相同。