web-dev-qa-db-ja.com

ジャンクションテーブルでのEF Core ThenInclude()の使用

.NET Framework(EF6)コードをASP.NET Core(EF Core)に転送していますが、この問題に出くわしました。コードの例を次に示します。

EF6では、熱心な読み込みにInclude()とSelect()を使用します。

return _context.Post
.Include(p => p.PostAuthor.Select(pa => pa.Author).Select(a => a.Interests))

PostAuthorはジャンクションテーブルであり、EF6に関与する必要のないジャンクションテーブル "AuthorInterest"もあります(Selectはa.Interestsに直接進みます)。

とにかく、EF7ではこれが修正されていることがわかります。つまり、ネストされたクエリにThenInclude()を使用する必要があるということです。しかしながら...

return _context.Post
  .Include(p => p.PostAuthor)
    .ThenInclude(pa => pa.Select(pa2 => pa2.Author))
...etc

上記のコードは、Select()ステートメントが原因で失敗します。 https://docs.efproject.net/en/latest/querying/related-data.html のドキュメントは、私はそれを必要とせず、すぐにAuthorにアクセスできることを示唆しているようですが、表示される最後のラムダのICollectionを取得するため、明らかにSelect()が必要です。クエリではさらに複数のジャンクションテーブルを調べますが、簡単にするために、最初のジャンクションテーブルだけに注目しましょう。

この作業を行うにはどうすればよいですか?

28
nikovn

しかし、表示された最後のラムダでICollectionを取得するので、明らかにSelect()が必要です

いいえ、あなたはしません。 EF Core Include/ThenIncludeは、EF6で使用されていたSelect/SelectManyの必要性を完全に置き換えます。どちらにも、コレクションおよび参照型のナビゲーションプロパティの個別のオーバーロードがあります。コレクションでオーバーロードを使用する場合、ThenIncludeはコレクションのタイプelementで動作するため、最後には常に単一のエンティティタイプになります。

あなたの場合、paはジャンクションテーブルの要素タイプに解決されるので、Authorに直接アクセスできる必要があります。

たとえば、EF6インクルードチェーン:

.Include(p => p.PostAuthor.Select(pa => pa.Author).Select(a => a.Interests))

eF Coreに変換します:

.Include(p => p.PostAuthor).ThenInclude(pa => pa.Author).ThenInclude(a => a.Interests)
45
Ivan Stoev