次の方法で共有


リレーションシップを介したクエリの実行 (LINQ to SQL)

更新 : November 2007

他のオブジェクトまたは他のオブジェクトのコレクションをクラス定義内で参照することは、データベース内の外部キー リレーションシップに直接対応します。クエリを実行するときにこのリレーションシップを使用するには、ドット表記を使ってリレーションシップ プロパティにアクセスし、オブジェクト間を移動します。これらのアクセス操作は、SQL で同等の複雑な結合または相関サブクエリとして変換されます。

たとえば、次のクエリでは、ロンドン在住の顧客からの注文のみが結果として得られるように注文から顧客へと移動します。

    Dim db As New Northwnd("c:\northwnd.mdf")
    Dim londonOrderQuery = _
From ord In db.Orders _
Where ord.Customer.City = "London" _
Select ord
        Northwnd db = new Northwnd(@"northwnd.mdf");

        IQueryable<Order> londonOrderQuery =
from ord in db.Orders
where ord.Customer.City == "London"
select ord;

リレーションシップ プロパティが存在しない場合は、これを結合として、SQL で記述するときと同じように手動で作成する必要があります。次にコードの例を示します。

    Dim db As New Northwnd("c:\northwnd.mdf")
    Dim londOrderQuery = _
From cust In db.Customers _
Join ord In db.Orders On cust.CustomerID Equals ord.CustomerID _
Select ord
        Northwnd db = new Northwnd(@"northwnd.mdf");
        IQueryable<Order> londonOrderQuery =
from cust in db.Customers
join ord in db.Orders on cust.CustomerID equals ord.CustomerID
where cust.City == "London"
select ord;

このようなリレーションシップは、リレーションシップ プロパティを使用すると一度に定義できます。こうすると、使いやすいドット構文を使用できるようになります。しかし、それだけがリレーションシップ プロパティの利点ではありません。なぜなら、通常はドメイン固有のオブジェクト モデルは階層構造またはグラフとして定義されるからです。プログラムで使用するオブジェクトには他のオブジェクトへの参照が含まれます。このオブジェクト間リレーションシップがデータベースの外部キー型リレーションシップに相当するのは、単なる幸運な偶然です。プロパティへのアクセスは、結合を記述するための便利な方法となります。

この点では、リレーションシップ プロパティは、クエリそのものよりもクエリの結果でより重要です。クエリによって特定の顧客に関するデータが取得された後で、クラス定義ではその顧客の注文が存在することが示されます。つまり、特定の顧客の Orders プロパティにその顧客のすべての注文が含まれると見なすことができます。実際には、これはクラスをこのように定義することにより宣言したコントラクトです。クエリによって注文が要求されなかった場合でも、ここに注文が含まれていると見なすことができます。オブジェクト モデルに対して期待されるのは、それがデータベースがメモリ内に拡張されたものであり、関連オブジェクトがすぐに使用できる状態にある、という錯覚を維持することです。

リレーションシップが得られたので、クラスに定義されたリレーションシップ プロパティを参照してクエリを作成できます。これらのリレーションシップ参照は、データベース内の外部キー リレーションシップに対応します。これらのリレーションシップを使用する操作は、SQL で同等の複雑な結合として変換されます。AssociationAttribute 属性を使用してリレーションシップを定義している限りは、明示的な結合を LINQ to SQL で記述する必要はありません。

この錯覚を維持するために、LINQ to SQL には遅延読み込みと呼ばれる機能が実装されています。詳細については、「遅延読み込みと即時読み込み (LINQ to SQL)」を参照してください。

たとえば、CustomerID-OrderID ペアのリストを射影する次の SQL クエリがあるとします。

SELECT t0.CustomerID, t1.OrderID
FROM   Customers AS t0 INNER JOIN
          Orders AS t1 ON t0.CustomerID = t1.CustomerID
WHERE  (t0.City = @p0)

このテーブル リレーションシップを次の図に示します。

リレーションシップをまたいだクエリ

LINQ to SQL を使用して同じ結果を得るには、Customer クラスに既に存在する Orders プロパティ参照を使用します。次のコードに示すとおり、Orders 参照からは、クエリを実行し、CustomerID-OrderID ペアを射影するために必要な情報が提供されます。

    Dim db As New Northwnd("c:\northwnd.mdf")
    Dim idQuery = _
From cust In db.Customers, ord In cust.Orders _
Where cust.City = "London" _
Select cust.CustomerID, ord.OrderID
        Northwnd db = new Northwnd(@"northwnd.mdf");
        var idQuery =
from cust in db.Customers
from ord in cust.Orders
where cust.City == "London"
select new { cust.CustomerID, ord.OrderID };

逆の操作も可能です。つまり、Orders にクエリを実行し、その Customer リレーションシップ参照を使用して、関連付けられた Customer オブジェクトに関する情報にアクセスできます。次のコードでは、前の例と同じ CustomerID-OrderID ペアを射影しますが、ここでは Customers ではなく Orders にクエリを実行しています。

    Dim db As New Northwnd("c:\northwnd.mdf")
    Dim idQuery = _
From ord In db.Orders _
Where ord.Customer.City = "London" _
Select ord.CustomerID, ord.OrderID
        Northwnd db = new Northwnd(@"northwnd.mdf");
        var idQuery =
from ord in db.Orders
where ord.Customer.City == "London"
select new { ord.Customer.CustomerID, ord.OrderID };

参照

その他の技術情報

LINQ to SQL のクエリの概念