2009-09-01 36 views
14

私はLINQ to SQLを使用して、SQL Server 2008のFullTextSearchストアドプロシージャの検索結果を取得しています。サーバーエクスプローラからデザイナにプロシージャをドラッグし、適切な戻り値の型とパラメータを使用してメソッドを作成しました。問題は、私はこのメソッドを呼び出す結果のCountを取得する必要があるので、私のリポジトリメソッド(Sprocメソッドを呼び出し、結果をIQueryableとして返す)を使用して、次の呼び出しを行います。クエリ結果は複数回列挙できません。

var result = repository.FullTextSearch(searchText); 
     int resultsCount = result.Count(); 
     var ret = result.Skip((pageNumber - 1) * PageSize).Take(PageSize).ToList(); 

このコードは、InvalidOperationExceptionが私はそれを実行しようとするたびに発生し、例外は、「クエリ結果は複数回列挙することはできません。」(ええ、あなたはそれを推測!)と言います

Sprocのために生成されたメソッドは、ISingleResultを返します。これはO.Kでなければなりません。私の知る限り。私はビューでページングをサポートする必要があるので、ページの総数を知る必要があります(AFAIKは再び可能です)。

私はここで何が欠けていますか?

+0

マーク・グラヴェルの推奨リファクタリングは最高ですが、goonaはこれに時間を割いています。私はマークの答えを取る!もう一度みんなありがとう! – Galilyou

答えて

14

これはストアドプロシージャを実行しているので、素敵なSkip/Takeは大部分が冗長です。すべてのデータを元に戻すことはできません(ストアドプロシージャの呼び出しは作成できません)。それができる唯一のことは、それらのいくつかのためにオブジェクトを具体化することではありません。より良いアプローチは、2つの呼び出しを行うためにコードをリファクタリングすることです場合

は、私は疑問に思う:

int result = repository.FullTextSearchCount(searchText); 
var result = repository.FullTextSearch(searchText, skip, take); // or similar 

すなわち使用して、SPROCのページングパラメータの一部を作る(およびデータベースでのフィルタリングにROW_NUMBER()/OVER(...) 、またはテーブル変数、一時-テーブルなど) - または代わりのSPROCでOUTPUTパラメータと似たような:

int? count = null; 
var result = repository.FullTextSearch(searchText, skip, take, ref count); 

(私はOUTPUTはになっていることを思い出しているようです、TSQL OUTPUTが本当に入力+出力なので)

+0

ここではリファクタリングの部分に完全に同意しますが、時間は現在許可されていません。今のところ、別のメソッドをリポジトリ "int FullTextSearchCount()"に追加すると思います。これは私が話すように動作するようです。リファクタリングのヒントはTo-Do now Marcにあります。 +1ありがとう。 – Galilyou

17

あなたができることはrepository.FullTextSearch(searchText)の後にToList()コールを追加することです。このようにして、結果はサーバから取得されます。その後、結果は(メモリにロードされているので)任意のもので処理できます。

あなたが今しようとしているのは、同じSQLクエリを2回実行することです。これはむしろ非効率的です。

+2

私は、FTSの結果全体を取り戻し、すべてを実現することは、2つの(ただし制約の多い)クエリを実行するよりも実質的に非効率的であると主張します。 –

+0

私もそうだと思います。私は、あなたがrwwildenを提案したときに.ToList()を追加すると、検索結果全体が得られることになります。私は今それらをすべて取得したくない、私はちょうどそれらの10がほしいので、私は.Skip()pingです。 – Galilyou

+0

結果セット全体をサーバに戻すことは、2つのクエリを実行するよりも効率が悪いことに同意します。しかし、それはストアドプロシージャコールなので、とにかく(Marcが彼の答えに正しく記されているように)起こります。 –

1

私は、カウントが必要な場合は、最初に結果を実行することをお勧めします。結果の実行でresultsCountを使用しないので、リスト自体からカウントを実行します。

var result = repository.FullTextSearch(searchText); 
var ret = result.Skip((pageNumber - 1) * PageSize).Take(PageSize).ToList(); 
int resultsCount = ret.Count(); 
+0

考え方は、resultsCountが結果の合計数を表していることです。 –

+0

うん、カマル!私はすべての結果のカウントを取得する必要があります。私が取るべき部分だけでなく、 – Galilyou

+0

お詫び申し上げます。私はそれを逃した! – Kamal

5

この問題を回避するには、ToList()を使用します。

var result = repository.FullTextSearch(searchText).ToList(); 
関連する問題