【问题标题】:Entity Framework Core and including child collections实体框架核心并包括子集合
【发布时间】:2016-11-18 19:45:38
【问题描述】:

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

此代码实质上是查找与传递的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
      }
    ]
  }
]

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

【问题讨论】:

    标签: c# asp.net entity-framework entity-framework-core


    【解决方案1】:

    我提出的所有问题都与我怀疑的一个答案有关。在搜索并完成它之后,您可以通过以下方式完成此操作:

    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 方法将我的对象整合到一个列表中,就像返回的第一个数据结构一样?

    在这种情况下,您不会因为SelectMany 用于展平列表列表。

    • 如何在以下情况下更精细地控制更改的属性? 以这种方式加载子集合?

    与第一个答案相同。

    • 如果我要加载多个子实体怎么办?

    与第一个答案相同。

    【讨论】:

      猜你喜欢
      • 2020-05-24
      • 2017-11-15
      • 1970-01-01
      • 2021-04-03
      • 1970-01-01
      • 1970-01-01
      • 2017-04-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多