2

データベースへの往復を減らすために、親オブジェクトの子コレクションを「プリロード」したいと考えていました。子コレクションを構成するオブジェクトを DataContext キャッシュにロードした場合、Linq2SQL はデータベースにアクセスする代わりにそれらのオブジェクトを使用することを期待していました。

たとえば、2 つの子コレクション (Children と Cars) を持つ Person オブジェクトがあるとします。

私はこれがうまくいくかもしれないと思った:

var children = from p in dbc.Person
               select p.Children;

var cars = from p in dbc.Person
           select p.Cars;

var people = from p in dbc.Person
             select p;


var dummy1 = children.ToList();
var dummy2 = cars.ToList();

foreach(var person in people){
    Debug.WriteLine(person.Children.Count);
}

person.Children.Countしかし、代わりに、すべての子が DataContext に既に読み込まれているにもかかわらず、への呼び出しごとにデータベースへの 1 回のトリップが発生します。

最終的に、私が探しているのは、データベースへのアクセスをできるだけ少なくして、完全なオブジェクト グラフ (複数の子コレクションを含む) をロードする方法です。

DataLoadOptionsクラス (および)は認識してLoadWithいますが、1 つの子コレクションに限定されており、これが問題です。

オブジェクトを余分に操作することなく、完全なオブジェクト グラフを作成できる (もちろん、Linq2SQL オブジェクトもある) 場合は、ストアド プロシージャを使用してもかまいません。

4

1 に答える 1

0

あなたが期待する方法で、LINQ-SQLまたはSQLでさえ、あなたが必要とすることが直接可能だとは思いません。

SQL がどのように機能するかを考えると、単一の一対多の関係は内部/左結合によって簡単にフラット化できます。この後、オブジェクトの別のセットが必要な場合は、理論的には、他のテーブルのすべての行を戻す別の左結合を作成できます。しかし、SQL が提供する出力を想像してみてください。オブジェクト グラフに戻すのは簡単ではありません。ORM は通常、このデータを提供するために行ごとにクエリを開始します。この例は、DataLoadOptionsLINQ-SQL を使用して複数のレベルを記述することです。これが見られるようになります。

また、多くの LEFT JOIN によるパフォーマンスへの影響は、単一のクエリの認識されている利点を簡単に上回ります。

あなたの例を考えてみましょう。これら 2 つのテーブルからすべての行をフェッチしています。これにより、さらに 2 つの問題が発生します。

  • テーブルには、予想よりもはるかに多くのデータが含まれる場合があります。SQL で数千行を一度にプルバックすると、パフォーマンスが低下する場合があります。次に、LINQ-SQL が一致するオブジェクトのリストを検索することを期待します。用途にもよりますが、SQL はこのデータをより速く提供できると思います。

  • あなたが期待する動作は隠されています。私にとっては、大きなテーブルで SELECT を実行すると、すべての行をキャッシュすることによってアプリのメモリ使用量が肥大化する可能性があることは珍しいことです。おそらく、オプションとして含めるか、独自の拡張メソッドを提供することができます。

解決

個人的には、LINQ-SQL の外部でデータをキャッシュすることを検討し始め、完全なオブジェクト グラフを作成するのに費用がかかると思われる場合は、ASP.Net / メモリ キャッシュ / あなたのキャッシュ プロバイダーからオブジェクトを取得します。

ビルトインのエンティティ リレーションシップに依存する1 レベルDataLoadOptions+ いくつかの手動キャッシュにより、おそらく多くの頭痛の種が解消されます。

私はこの特定の問題に数回遭遇しましたが、まだ何も考えていません。

于 2013-04-10T18:40:40.993 に答える