Entity Framework Core和包含子集合

3
基本上我想做的是查询父实体的子集合。根据EF Core文档,我可以使用IncludeThenInclude方法来实现这一点(https://learn.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;
}

这段代码主要是查找与传递的id相匹配的Matchups实体。然后它会包含模型上的导航属性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
      }
    ]
  }
]

这很好,但是它给了我比我真正感兴趣的更多的数据。例如,我更希望我的用户属性只有一个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 方法将对象对齐到一个列表中,就像第一种返回的数据结构一样?
  • 在以这种方式加载子集合时,如何更精细地控制更改属性?
  • 如果有多个子实体需要加载怎么办?
1个回答

5

我提出的所有问题都与我怀疑的一个答案有关。经过搜索和努力,以下是您可以实现这一点的方法:

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 并从子列表中进行投影。这回答了我提出的以下问题:
- 是否有一种方法可以查询子数据而不使用 Include? - 我很难相信这是唯一的方法。
只需使用 Select 方法将子列表投影到导航属性中即可。
如何像第一个返回的数据结构一样将对象合并到一个列表中?
在这种情况下,您不会这样做,因为 SelectMany 用于展平列表的列表。
如何在以这种方式加载子集合时获得更精细的控制更改属性?
与第一个答案相同。
如果我有多个子实体要加载怎么办?
与第一个答案相同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接