2011-12-22 5 views
2

ページングされた結果を提供するクエリを構築する必要があります。フィルタリングの一部はデータベースで発生し、その一部はメモリ内のオブジェクトで発生します。データベースとオブジェクトクエリをlinqで混合し、ページングされた結果を提供

以下は、データベースに対してlinqクエリを実行し、さらにカスタムコードを使用してそれをフィルタリングしてから、ページングにskip/takeを使用する方法を示した簡単なサンプルですが、これは非常に非効率的ですクエリの最初の部分と一致するすべての項目を読み込みます。

Things.Where(e=>e.field1==1 && e.field2>1).ToList() 
      .Where(e=>Helper.MyFilter(e,param1,param2)).Skip(m*pageSize).Take(pageSize); 

myFilterを関数は、データベース内に配置されておらず、それは追加のパラメータ(上記の例でparamX)

で実行され、追加のデータを使用して初期をロードせずにこのような状況に対処するための好ましい方法はあります結果は完全にメモリに格納されます。

答えて

1

はい、データベースレベルでクエリとページ。 Helper.MyFilterのロジックがSQLクエリに含まれている必要があります。

その他のオプション。これは、コードベースをより侵害します。エンティティが変更されたときに、ビューモデルとドメインエンティティを保存することです。ビューモデルの一部にはHelper.MyFilter(e)の結果が含まれているため、迅速かつ効率的にクエリを実行できます。

+0

MyFilter関数がdbにない追加情報を使用するため、最初のオプションは使用できません。 Myfilterの結果を保存するには、Myfilterに実際に追加のパラメータがあるため実行できません。私はそれに応じて質問を更新しました。 – cellik

+0

MyFilterの結果をデータベースに保存する場合、計算方法は関係ありません。データベースを照会しているときではなく、エンティティが変更されたときに保存しています。 –

+1

データベース外の要件がある場合は、結果をデータベースにページする方法がないため、ページングする前に結果をメモリにロードする必要があります。 –

1

上記のエンティティフレームワークは、.Skip()。Take()をサポートしています。したがって、すべてをdbレベルに送り、あなたの場所をEFが消費できるものに変換します。

ヘルパーは、複雑な使用Albahariの述語ビルダーは、あなたのどこ場合:

http://www.albahari.com/nutshell/predicatebuilder.aspx

またはわずかユニバーサル述語Builderを使用する方が簡単:上記に基づいて

http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/

0
.ToList() 

クエリをメモリオブジェクト、つまりリストに変換して、クエリを実行してから、データにページングを提供しています。

あなたは1つのWhere句でそれをすべてを置くことができます。

Things.Where(e=>e.field1==1 && e.field2>1 
      && e=>Helper.MyFilter(e)).Skip(m*pageSize).Take(pageSize); 

、その後.ToList()。 そのようにすれば、LinqにSqlにクエリを生成し、必要なデータだけを得る機会が与えられます。

または、メモリオブジェクトに変換してフィルタリングするだけの理由がありますか?私はその点を見ませんが。データベースに対して実際に実行する前に、Linq to Sqlクエリで必要としない結果を除外することができます。

EDIT

私はあなたがいくつかのオプションを持って議論から見ることができるように。

多くのデータがあり、書き込みより多くの読み取りを行う場合は、可能であればHelper.MyFilterの結果をデータベースに保存することをお勧めします。そうすれば、データベースからすべてのデータを取得せずに、SELECT自体のフィルタリングされたデータが増えるため、selectのパフォーマンスを向上させることができます。

もう1つの方法があります。 Helperクラスは別のアセンブリに入れてreference that assembly from SQL Serverとすることができます。これにより、ページングロジックをデータベースに配置してコードを使用することができます。

+0

これは 'Helper.MyFitler(e)'のロジックをsqlに変換できると仮定しています。 –

+0

Jasonが述べたように、この関数にはSQLに変換できないコードが含まれているため、これは機能しません。だからこそ私はToList – cellik

+0

@cellikを使いました - あなたはすべてを正確な順序で行う必要がありますか?私は多分、あなたが "並べ替え"を使ってクエリを "部分的に最適化"できると考えていました:。 e => Helper.MyFilter(e)) – TheBoyan

関連する問題