QA@IT

Entity Framework 異なるDBのテーブルのJoin

10301 PV

VisualStudio2013 VisualBasic
SQL Server 2012

Entity Frameworkを試しているのですが、異なるDBのテーブルをJOINしてデータを取得する方法がわかりません。

データベース D1のテーブル Table01
データベース D2のテーブル Table02

SQLなら以下の様な書き方で取得できます。
(D1に接続する前提で)
Select T1.Column1, T2.Column2
From Table01 T1 Inner Join D2.dbo.Table02 T2 ON T1.ID=T2.ID

Entity FrameworkはDB毎にContextが作成されるようですが、以下の様な方法を試したところ、
異なるContextを見ているからだめのようでエラーとなります。

Using context1 As New DB1Entities
    Using context2 As New DB2Entities

        Dim rows = From p In context1.Table01
                      Join c In context2.Table02
                      On p.ID Equals c.ID
                      Select (New With {
                        .Column1 = p.Column1,
                        .Column2 = c.Column2}
                      )
    End Using
End Using

アドバイスの程よろしくお願い致します。

回答

List<T> 型のオブジェクトを「データベース D1のテーブル Table01」と「データベース D2のテーブル Table02」のそれぞれに作って、それを linq で join すれば可能と思います。

実際には DB は別ではないですが、以下のようにして期待通りに join された結果が得られることは確認できました。(ASP.NET MVC で マイクロソフトが提供しているサンプルデータベース AdventureWorksLT_Data.mdf から Visual Studio のウィザードを利用して EDM を作成しています)

ToList() がないと "System.NotSupportedException: 指定された LINQ 式には、別のコンテキストに関連付けられているクエリへの参照が含まれています。" という例外(多分、質問者さんのと同じ)がスローされます。

namespace Mvc4App.Controllers
{
    public class JoinedList
    {
        public int OrderID { get; set; }
        public int CustomerID { get; set; }
        public String CompanyName { get; set; }
    }

    public class AddressController : Controller
    {
        public ActionResult InnerJoin()
        {
            var db1 = new AdventureWorksLT_DataEntities();
            var db2 = new AdventureWorksLT_DataEntities();

            var list1 = (from s in db1.SalesOrderHeader select s).ToList();
            var list2 = (from c in db2.Customer select c).ToList();

            var list = from s in list1
                       join c in list2
                       on s.CustomerID equals c.CustomerID
                       select new JoinedList { OrderID = s.SalesOrderID, CustomerID = s.CustomerID, CompanyName = c.CompanyName };

            return View(list);
        }

        // ・・・中略・・・

    }
}
編集 履歴 (0)
  • 素晴らしいです。
    自分なりにはSQL文を直接実行する方法で一応動作していました。
    Dim list = context1.Database.SqlQuery(Of MyEntityClass)("Select * ・・")
    しかし、DB構造を意識しないという点を考えると、教えていただいた方法が良いですね。
    こちらでも動作しました。ありがとうございました。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。