EF CoreでJOINを複数する方法
概要
ASP.NET Coreでデータベースへクエリを発行する際に、Entity Framework Core(EF Core)を使うのが一般的です。
今回、久しぶりにASP.NET Coreで1対多や多対多のリレーションを作成したのですが、Entity Framework Coreでリレーション先のデータを取得する方法に悩んでしまったので、備忘録として残しておきます。
環境
- .NET 5
- Entity Framework Core 5
- ASP.NET Core 5
Includeを使った別テーブルのデータの読み出し
例えば、一つの記事(Articles)に複数のタグ(Tags)が結びつくような構造をもったテーブルを考えます。SQLとしては、JOINを使うようなものになります。
結論から話すと、次のようなコードで実現できます。
context.Articles
.Include(a => a.Tags)
.First()
このようにIncludeを使うことで、Articlesテーブルに紐づいた複数のTagsデータを取得できます。Includeは複数記述することが可能なので、例えばArticlesテーブルにカテゴリ(Categories)テーブルのリレーションがある場合は、次のようになります。
context.Articles
.Include(a => a.Tags)
.Include(a => a.Categories)
.First()
ここまでは調べるとすぐに情報を見つけることができました。
私が本当に知りたかったのは、Includeで取得したデータからさらにIncludeのようなものでデータを取得するということです。SQLでいうならば、JOINでテーブルを結合してさらにJOINでテーブルを結合するというようなものです。
例えば、カテゴリからカテゴリの所有者を表すユーザー(Users)テーブルのリレーションがあったとします。そのような場合、次のようにすることで記事からユーザーの情報まで取得することができます。
context.Articles
.Include(a => a.Tags)
.Include(a => a.Categories)
.ThenInclude(c => c.Users)
.First()
Includeの直後にThenIncludeを記述することで、直前のIncludeで取得するデータについて、さらにデータを取得することができます。必ずThenIncludeはIncludeの直後に書かないといけないので、ここだけは注意が必要です。また、ThenIncludeもIncludeと同じように複数使うことができます。
これで、私が知りたいことを知ることができました。
さいごに
ASP.NET CoreやEntity Framework Coreの情報はあまり多くないので、少し見つけ出すのに苦労しました。
IncludeやThenIncludeは、組み合わせ爆発のような問題が発生することもあるので、利用する際は色々と気を付ける必要がありそうです。