2016-11-18 51 views
1

基本上我想要做的是查詢父實體的子集合。根據EF核心文件,我可以使用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方法將我的對象與第一個數據結構返回一致?
  • 以這種方式加載子集合時,如何更改粒度控制來更改屬性?
  • 如果我有多個子實體加載會怎麼樣?

回答

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來平整列表清單。

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

與第一個答案相同。

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

與第一個答案相同。