1

実際にクエリを実行せずにネストされたリストを怠惰にロードするにはどうすればよいですか?非常に基本的な例を使用して、私が持っていると言う:Linq2Sql - ネストされたリストをどうやって読み込むのですか?

class CityBlock { 
    IList<Building> BuildingsOnBlock; 
    Person BlockOwner; 
} 

class Building { 
    IList<Floor> FloorsInBuilding; 
} 

class Floor { 
    IList<Cubicle> EmployeeCubicles; 
} 

Class Cubicle { 
    System.Guid CubicleID; 
    Person CubicleOccupant; 
} 

とし、その後、私のリポジトリ層に、私は次のような方法があります。

GetCityBlocks() 

そして、サービス層では、私が持っているでしょうGetCityBlocksByOwnerを、我々は.ToListは()リポジトリに実行するために起こって行う場合

GetCityBlocks().ForOwner("Guido") 

:私たちはちょうどグイドのブロックをしたいと言う、特定の人物が所有する都市・ブロックを取得するために拡張メソッドを利用しますクエリ - 私たちは誰がそのレベルに到達しているのかわからないのでばかげているでしょう。ですから問題は、これをいかに効率的に行うかです。

ブロック所有者が50000人、都市ブロックが1000000人いるとしましょう。それらのすべてをロードすることはオプションではありません。 IQueryablesを使用することは、ネスティングのためには機能しません(極端なハッキングはありません。少なくとも私が知っていることです)。また、私がRob ConeryのLazyListのようなものを使用しようとすると、私たちは基本的に私たちのドメインモデルへのDALからの漏洩があります。これは将来非常に悪いことがあります。

これを正しく実行するにはどうすればよいですか?

  • 正しい状況を判断するのは問題ですか?その場合は、 リポジトリレイヤーまたは サービスレイヤーでこれを行いますか?
  • 非常に具体的なサービス方法を得るために、サービスレイヤーと私のリポジトリレイヤーを一緒に半分にしますか?
  • 何か完全に欠けていますか? (まだとにかくそう を段階的に廃止されるLinq2Sql もの、に比較的新しい...)

編集:リポジトリパターンでは 、我々は現在、当社のドメインオブジェクトにマッピングしている、それはそうこのようなものになります - ない仕事に、このために

public IQueryable<CityBlock> GetCityBlocks(){ 
    var results = from o in db.city_blocks 
        let buildings = GetBuildingsOnBlock(o.block_id) 
        select new CityBlock { 
         BuildingsOnBlock = buildings, 
         BlockOwner = o.block_owner 
        }; 
    return results; 
} 

を我々はCityBlockオブジェクトのIQueryableに、実際のフィールドを作成しない限り、我々は、建物が).ToListを(得ることを確認する必要があると思いますCitにアクセスする人にはあまりにも多くの権限が与えられるように思えるからyBlock.BuildingsOnBlockフィールド。このマッピングはドメインオブジェクトにマッピングされていますか?

+0

を始めるためのリンクです。それは改善の点で大きな注目を集めることはないが、それはすでにフレームワークに入っているので、しばらく私たちと一緒に行くだろう。とにかく、StackOverflowはSQLにLinqを使用して、私はそれがかなりうまくいくと思います。 –

+0

GetCityBlocks()メソッドから何を返すのですか?拡張フィルタを使用しているので、既にIQueryableを返すのでしょうか?そうでなければ、本当にロバートの答えを使うべきです。リポジトリからIQueryableを公開するとLinq2Sql以外のLinqが公開されるだけであることに注意してください。 – Jaime

答えて

1

IListsではなくIQueryablesを返すことで行います。

ToList()は、IQueryableからIListに変換を実行する必要があるため、クエリをすぐに実行させます。

IQueryablesを返す限り、レイジーローディングはデータが実際に必要になるまで、つまりToList()が呼び出されるまで実行を延期する必要があります。

私は現時点で参考文献を見つけることができませんが、このようにすると、linq to sqlはサーバーに送信するSQLを最適化する機会があります。言い換えれば、それは最終的にこれらのレコードを読みます:

GetCityBlocks().ForOwner("Guido") 

ではなく、これらのレコード:

GetCityBlocks() 
+0

ドメインモデルのIQueryablesは、そのドメインの一部であるためではなく、DALの実行だけを行っているという事実のために、モデル。 IQueryableは、必ずしもそのオブジェクトのフィールド/プロパティ/クラスオブジェクトを照会するために必要なものではありません。または私はまだこの問題を間違って見ていますか? – MunkiPhD

+0

サービス層にIQueryablesを返すと、サービス層には「明確なインタフェース」がないという視点があります(クエリーを操作するにはあまりにも力があります)。だからトレードオフがある。リポジトリは、すべての可能なクエリに対してメソッドを必要としないため、非常に簡単になります。また、必要な処理を行うというメリットもあります。私はパターンの弁護士ではないので、あなたはあなたがこのようにすることはできないと言いませんが、他の誰かがそうするかもしれません。 –

+0

私はコントロールを少し緩くすることに同意しますが、リポジトリ内の独自のオブジェクトにマッピングする場合はどうなりますか?これは他の場所でやるべきことですか? (私の編集を参照してください) – MunkiPhD

0

あなたはそれを動作させるためにあなたのドメインオブジェクトをマップに異なるアプローチを試みることができます。問題は、あなたが何をしていても(あなたのリストをあなたのドメインオブジェクトのIQueryableに変更しない限り)、あなたはマッピング中にToList()を終了します。

linq2Sqlにカスタムdatacontextを作成し、マッピングのためにデザイナを使用しないで、あなたのPOCOへのマッピングを行わせるもう1つの方法:)あなたのドメインモデルをきれいに保ち、linq2Sqlに正しい依存関係時間。このルートに入ることにはそれ自身の問題があることに注意してください。

ここでは、全体の段階的なものは赤ニシンです。このルート

Achieving POCO s in Linq to SQL

関連する問題