Entity Framework Core でテーブルのLEFT JOIN (テーブル結合)をする - C#

Entity Framework Core でテーブルのLEFT JOIN (テーブル結合)をするコードを紹介します。

概要

こちらの記事ではJOIN(INNER JOIN)のコードを紹介しました。 この記事では、Entity Framework Core でテーブルをLEFT JOINして対応する値を取得するコードを紹介します。

LEFT JOINを実行する場合は、GroupJoin メソッドを利用し、SelectManyメソッド内で、DefaultIfEmpty() メソッドを呼び出します。

書式

メソッド構文

LEFT JOINですべてのフィールドを取得する場合の書式は以下になります。
結果は匿名型(Anonymous型)で戻るため、IQueryable<dynamic> 型の変数に代入します。
(結合元テーブルのDbSet)
.GroupJoin(
  (結合先テーブルのDbSet), (結合元テーブルの一時名) => (結合元テーブルの一時名).(JOIN対象のフィールド), 
  (結合先テーブルの一時名)=> (結合先テーブルの一時名).(JOIN対象のフィールド), 
  ( (結合元テーブルの返却オブジェクトのフィールド名), (結合先テーブルの返却オブジェクトのフィールド名) )
    => new { (結合元テーブルの返却オブジェクトのフィールド名), (結合先テーブルの返却オブジェクトのフィールド名) })
.SelectMany(
  (レコードの一時名) => (レコードの一時名).(GroupJoin先のテーブルのオブジェクト).DefaultIfEmpty(),
  ( (レコードの一時名), (Join先レコードの一時名) ) 
    => new { レコードの一時名).(Join元のテーブルオブジェクト), (Join先レコードの一時名) });

プログラム例

テーブルの準備

データベースに以下のテーブルを用意します。
ProductsD テーブルのstockplace フィールドと ProductsDStockPlace テーブルの id フィールドを結合した結果を取得します。
ProductsD テーブル
id name stockplace category price
1 ぺんぎんクッキー 1 1 180
2 らくだキャラメル 3 2 95
3 しろくまアイス 2 3 230
4 かるがもサブレ 1 1 160
5 あるぱかカステラ 2 2 420
6 あひるタルト 4 1 260
ProductsDStockPlace テーブル
id name
1 東京
2 札幌
3 福岡

UI

下図のフォームを作成します。ボタンとMultilinesプロパティをTrueに設定したテキストボックスを配置します。

コード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using EntityFrameworkCoreJoin.Models;

namespace EntityFrameworkCoreJoin
{
  public partial class FormLeftJoin : Form
  {
    public FormLeftJoin()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      IQueryable<dynamic> rec;
      IPentecSandBoxContext sc = new IPentecSandBoxContext();

      rec = sc.ProductsDs.GroupJoin(sc.ProductsDstockPlaces, pd_table => pd_table.Stockplace, pdsp_table => pdsp_table.Id, (pd_table, pdsp_table) => new { pd_table, pdsp_table })
        .SelectMany(rec => rec.pdsp_table.DefaultIfEmpty(), (rec, pdsp_table2) => new { rec.pd_table, pdsp_table2 });

      foreach (var r in rec) {
        textBox1.Text += string.Format("{0} \\{1:d} : {2}\r\n", r.pd_table.Name.Trim(), r.pd_table.Price, r.pdsp_table2?.Name.Trim());
      }

    }
  }
}

解説

LEFT JOINを実行するLINQが以下のコードです。
  rec = sc.ProductsDs
    .GroupJoin(sc.ProductsDstockPlaces, pd_table => pd_table.Stockplace, pdsp_table => pdsp_table.Id, (pd_table, pdsp_table) => new { pd_table, pdsp_table })
    .SelectMany(rec => rec.pdsp_table.DefaultIfEmpty(), (rec, pdsp_table2) => new { rec.pd_table, pdsp_table2 });

GroupJoinを実行します。JOIN元のテーブルProductsDのStockplaceフィールドとJOIN先のテーブルProductsDStockPlaceのIdフィールドで結合します。
GroupJoinの動作の詳細はこちらの記事を参照してください。
.GroupJoin(sc.ProductsDstockPlaces, pd_table => pd_table.Stockplace, pdsp_table => pdsp_table.Id, (pd_table, pdsp_table) => new { pd_table, pdsp_table })

SelectManyメソッドで、GroupJoinの結果から、DefaultIfEmpty()メソッドを呼び出します。
    .SelectMany(rec => rec.pdsp_table.DefaultIfEmpty(), (rec, pdsp_table2) => new { rec.pd_table, pdsp_table2 });

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


[button1]をクリックします。下図の結果が表示されます。
Join先が無いid=6 の"あひるタルト"のレコードも結果に表示される動作が確認できます。


実行されるSQL文を確認します。LEFT JOINのSQL文が実行されています。


SELECT [p].[id], [p].[category], [p].[name], [p].[price], [p].[stockplace], [p0].[id], [p0].[name]
FROM [ProductsD] AS [p]
LEFT JOIN [ProductsDStockPlace] AS [p0] ON [p].[stockplace] = [p0].[id]
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2023-07-08
作成日: 2023-07-08
iPentec all rights reserverd.