LINQ to Entitiesで複数キーのJoin
LINQ to Entitiesを使って、データベースのテーブルで複数のキーを使ったJoinを実現するには、匿名型で複数のキーを含むclassを作ればいい。
LINQ to EntitiesでJoinを組むと、慣れないとけっこう苦労したりする。単純なキーのJoinなら比較的に簡単だが、複数のキーをJoinするにはどうすればいいか悩んだことがあった。調べた結果、匿名型でキー項目を含むclassを作って、そのclass同士をequalsで結べばいいことがわかった。
以下に例を挙げてみる。
まずはTestという名前のデータベースを作成してTestA、TestBというテーブルを作成する。それぞれキー項目が二つになるようにTestIDとTestCodeを作成する。
TestID | TestCode | Data -------|----------|-------- 1 | 101 | Data_1 2 | 102 | Data_2 3 | 103 | Data_3 4 | 104 | Data_4 5 | 105 | Data_5 ...(続くとする)
TestID | TestCode | Flag -------|----------|------ 1 | 101 | 1 2 | 102 | 2 3 | 103 | 3 4 | 104 | 4 5 | 105 | 5 ...(続くとする)
これらのテーブルから以下のような結果を取得したい。
TestID | TestCode | Data | Flag -------|----------|--------|------ 1 | 101 | Data_1 | 1 2 | 102 | Data_2 | 2 3 | 103 | Data_3 | 3 4 | 104 | Data_4 | 4 5 | 105 | Data_5 | 5 ...(続くとする)
この結果をSQLで組んだ場合は比較的簡単だ。ただJoinで結べばいい。
select a.TestID, a.TestCode, a.Data, b.Flag from TestA a
inner join TestB b on a.TestID = b.TestID and a.TestCode = b.TestCode
これをLINQ to Entitiesで実現するには以下のようにする。
using System;
using System.Linq;
namespace LinqToEntitiesJoin
{
class Program
{
static void Main(string[] args)
{
var entities = new TestEntities();
var test = from a in entities.TestA
join b in entities.TestB on new { a.TestID, a.TestCode } equals new { b.TestID, b.TestCode }
select new { a.TestID, a.TestCode, a.Data, b.Flag };
test.ToList().ForEach(item =>
{
Console.WriteLine("TestID = {0}, TestCode = {1}, Data = {2}, Flag = {3}", item.TestID, item.TestCode, item.Data, item.Flag);
});
}
}
}
ハイライトになっているところが味噌で、匿名型でキー項目を含むclassを作成して、それ同士をequalsで結んで同じ結果が返ってくるようにしている。
これで複数のキーでJoinされたデータの結果を取得することができる。
以下のようにclassを作成して明示的に指定してもかまわない。
using System;
using System.Linq;
namespace LinqToEntitiesJoin
{
class Program
{
private class Key
{
public int TestID { get; set; }
public int TestCode { get; set; }
}
static void Main(string[] args)
{
var entities = new TestEntities();
var test = from a in entities.TestA
join b in entities.TestB on new Key() { TestID = a.TestID, TestCode = a.TestCode } equals new Key() { TestID = b.TestID, TestCode = b.TestCode }
select new { a.TestID, a.TestCode, a.Data, b.Flag };
test.ToList().ForEach(item =>
{
Console.WriteLine("TestID = {0}, TestCode = {1}, Data = {2}, Flag = {3}", item.TestID, item.TestCode, item.Data, item.Flag);
});
}
}
}