Entity Frameworkコアと子コレクションを含む

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

質問

基本的には、親エンティティのクエリ子コレクションです。 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;
}

このコードは、渡された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プロパティの値を持つようにuserプロパティを設定します。それ以外は、これは私が望むデータ構造です、私はただいくつかのプロパティを変更したいだけです。

答えを見てみると、 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
    }
  }
]

これにはいくつかの欠点があります。 1つは、関連するデータのどれもがロードされておらず、それらがコレクション内にあるべきであるときにplayersための2つの別々のオブジェクトであるということです。

だから、私は同じ答えに関連していると信じているいくつかの質問があります:

  • Includeを使用せずに子データを照会できる方法はありIncludeか?私はこれが唯一の方法だと信じるのは難しいと思う。
  • 返される最初のデータ構造体のように、 SelectManyメソッドを使用してオブジェクトを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を使用して、あなたの子リストの投影を使用することです。これは私が提起した以下の質問に答えます:

  • インクルードを使用せずに子データを照会できる方法はありますか?私はこれが唯一の方法だと信じるのは難しいと思う。

Selectメソッドを使用して、子リストからナビゲーションプロパティに投影してください。

  • 返される最初のデータ構造体のように、 SelectManyメソッドを使用してオブジェクトを1つのリストにリコンサイルするにはどうすればよいですか?

SelectManyはリストのリストを平坦化するために使用されます。

  • この方法で子コ​​レクションをロードするときに、プロパティを変更する方法をより細かく制御するにはどうすればよいですか?

最初の答えと同じです。

  • ロードする子エンティティが複数ある場合はどうなりますか?

最初の答えと同じです。



Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ