實體框架核心並包括子集合

asp.net c# entity-framework entity-framework-core

基本上我要做的是查詢父實體的子集合。根據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;
}

此代碼主要查找匹配傳遞的idMatchups實體。然後它出去並包括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方法將對象與一個列表進行協調,就像返回的第一個數據結構一樣?
  • 以這種方式加載子集合時,如何更好地控制更改屬性?
  • 如果我要加載多個子實體怎麼辦?

一般承認的答案

我提出的所有問題都與我懷疑的單一答案有關。在搜索並完成它之後,您可以通過以下方式完成此操作:

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用於展平列表列表。

  • 以這種方式加載子集合時,如何更好地控制更改屬性?

與第一個答案相同。

  • 如果我要加載多個子實體怎麼辦?

與第一個答案相同。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因