ランタイム内のオブジェクトには一意の ID があります。 同じオブジェクトを参照する 2 つの変数は、実際にはオブジェクトの同じインスタンスを参照します。 このため、1 つの変数のパスを使用して行った変更は、もう一方の変数を通じてすぐに表示されます。
リレーショナル データベース テーブル内の行には一意の ID がありません。 各行には一意の主キーがあるため、同じキー値を共有する 2 つの行はありません。 ただし、この事実はデータベース テーブルの内容のみを制約します。
実際には、ほとんどの場合、データはデータベースから取り出され、アプリケーションで動作する別の層に取り込まれます。 これは、LINQ to SQL がサポートするモデルです。 データがデータベースから行として取り出されると、同じデータを表す 2 つの行が実際に同じ行インスタンスに対応するとは思われません。 特定の顧客に対して 2 回クエリを実行すると、2 行のデータが取得されます。 各行には同じ情報が含まれています。
オブジェクトでは、非常に異なる何かが期待されます。 同じ情報を DataContext に繰り返し要求すると、実際には同じオブジェクト インスタンスが提供されます。 オブジェクトはアプリケーションにとって特別な意味を持ち、オブジェクトのように動作することが期待されるため、この動作が期待されます。 階層またはグラフとして設計しました。 同じものを複数回要求したからといって、それらを取得し、多数のレプリケートされたインスタンスを受け取らないことを期待します。
LINQ to SQL では、 DataContext はオブジェクト ID を管理します。 データベースから新しい行を取得するたびに、その行は主キーによって ID テーブルに記録され、新しいオブジェクトが作成されます。 同じ行を取得するたびに、元のオブジェクト インスタンスがアプリケーションに返されます。 このように、 DataContext は、データベースで見られる ID の概念 (つまり、主キー) を言語 (つまりインスタンス) で見られる ID の概念に変換します。 アプリケーションでは、最初に取得された状態のオブジェクトのみが表示されます。 異なる場合、新しいデータは破棄されます。 詳細については、「 ID キャッシュからのオブジェクトの取得」を参照してください。
LINQ to SQL では、このアプローチを使用して、オプティミスティック更新をサポートするためにローカル オブジェクトの整合性を管理します。 オブジェクトが最初に作成された後に発生する変更は、アプリケーションによって行われた変更だけなので、アプリケーションの意図は明確です。 外部のパーティによる変更が中間で発生した場合は、 SubmitChanges()
が呼び出された時点で識別されます。
注
クエリによって要求されたオブジェクトが既に取得されたものとして簡単に識別できる場合、クエリは実行されません。 ID テーブルは、以前に取得したすべてのオブジェクトのキャッシュとして機能します。
例示
オブジェクト キャッシュの例 1
この例では、同じクエリを 2 回実行すると、毎回メモリ内の同じオブジェクトへの参照を受け取ります。
Customer cust1 =
(from cust in db.Customers
where cust.CustomerID == "BONAP"
select cust).First();
Customer cust2 =
(from cust in db.Customers
where cust.CustomerID == "BONAP"
select cust).First();
Dim cust1 As Customer = _
(From cust In db.Customers _
Where cust.CustomerID = "BONAP" _
Select cust).First()
Dim cust2 As Customer = _
(From cust In db.Customers _
Where cust.CustomerID = "BONAP" _
Select cust).First()
オブジェクト キャッシュの例 2
この例では、データベースから同じ行を返す異なるクエリを実行すると、毎回メモリ内の同じオブジェクトへの参照を受け取ります。
Customer cust1 =
(from cust in db.Customers
where cust.CustomerID == "BONAP"
select cust).First();
Customer cust2 =
(from ord in db.Orders
where ord.Customer.CustomerID == "BONAP"
select ord).First().Customer;
Dim cust1 As Customer = _
(From cust In db.Customers _
Where cust.CustomerID = "BONAP" _
Select cust).First()
Dim cust2 As Customer = _
(From ord In db.Orders _
Where ord.Customer.CustomerID = "BONAP" _
Select ord).First().Customer