2016-04-19 10 views
2

Linq to Entitiesを使用すると、書かれたLINQ文で作成されたLinqオブジェクトでWhere lamba式を実行するとwhere節が機能しません。Where節がLINQ IQueryableクエリで機能しない

これは機能しません。クエリは実行されますが、結果はフィルタリングされずに返されます。

var myQuery = (from l in db.MyTable 
        select l); 
myQuery.Where(r => availableStatusList.Contains(r.Status)); 
var myObj = myQuery.ToList(); 

これは機能します。クエリが実行され、結果が適切にフィルタリングされて返されます。

var myQuery = (from l in db.MyTable 
        select l).Where(r => availableStatusList.Contains(r.Status)); 
var myObj = myQuery.ToList(); 

私が理解する限り、これらの両方で同等の結果が返されます。最初のものがWhere句に耳を傾けない理由は何ですか?

+3

あなたはdidnの」

は、文字列のミューテータ機能と同様に

、あなたが戻って変数に代入する必要がありますそれをmyQueryに割り当てます。 'Where'節は新しいオブジェクトを作成し、既存のオブジェクトを変更しません。 –

+0

'where'を同じ元のフォーマット(標準からインラインのフォーマットを混在させない)に入れてみてください:lからdb.MyTable where availableStatusList.Contains(l.Status)select l;私はそれがそれを変えるかどうかを知りたいのです。 – BlackjacketMack

答えて

5

Where句は、呼び出されたときに新しいオブジェクトを作成しません。最終的に実行されるフィルターにコレクションをラップすることによって、既存のコレクションにフィルターを適用します。しかし、それは純粋な関数なので、そのフィルタの戻り値は元の参照myQueryに戻される必要があります。そのため、2番目の例が機能します... Where()節を使用して結果をmyQueryにチェーンしました。フィルタリングされたコレクションを戻し、遅延クエリをToList()で実現します。

最初の例では、フィルタがコレクションに直接適用されていると仮定していますが、ファンクションが呼び出されたときにフィルタがコレクションをすぐに変更しないため、は機能しません。むしろ、オリジナルのQueryableコレクションに「添付」されていて、クエリをToList()で解決するという条件付きで適用される述語のみを適用します。

遅延実行が一連の約束事であると考えるのは時々簡単です。

私はあなたに1ドルを払うと、1ドルがあります。私が税金を25セント払うと、すぐにが取引(クエリ)を解決しました。

しかし、私は火曜日に1ドルを提供すると約束したら、Queryable<T>約束を返しました。

今と火曜日の間に複数のイベントが発生する可能性があります。私は、税金(25セント)、ガムの棒(25セント)のフィルター、または他のフィルターを連鎖させることができます。

しかし、私たちの簿記システムには警告があります。約束した金額のうち、.Taxes()Where句)に電話して更新することはできません。 レコード約束金額に対して当社の取引を元の変数に戻し、約束した額に対して発生した取引で更新することにより、火曜日に

myQuery = myQuery.Where(condition); 

あなたが(チェーンの約束/一連のフィルタにToList()を呼び出すことによって)お支払いを収集するために来るとき、私は50セントの支払いが生じ、約束したものから発生したものを控除します。それは仕事での延期された実行です。

+1

私は、 'Where'句が実際には新しいフィルタリングされたienumerableを返すと考えました。 var list = new List {"hi"、 "bye"}; Assert.AreNotSame(list、list.Where(w => w == "hi")); – BlackjacketMack

+1

@BlackjacketMack IEnumerableはIQuerableではありません。強調の答えを更新しました。さらに、あなたの比較は無効です。あなたのタイプを比較するタイプのIEnumerableが無効です。基になるコレクションは変更されていませんが、それらは同じ型ではありません。参照の点で「オブジェクト」と話している場合は、新しい参照が作成されます。基になるコレクションに関して「オブジェクト」と言えば、いいえ、新しいコレクションは作成されず、クエリが実現されるまで返されません。 –

+0

私は参照しています...ので、IQueryableは変更を取得し続けますが、同じ参照を保持しますか?だから、Assert.AreSame()が渡す句を追加する場合は? IEnumerablesのように、linq句を追加すると、新しいIQueryableが返され、デコレータとして以前のステートメントを効果的にラップするという印象を受けました。 – BlackjacketMack

3

短い答え:

string sample = "text"; 

// this doesn't change sample 
sample.ToUpper(); 

// this one does 
sample = sample.ToUpper(); 

だから、何が必要です:

myQuery = myQuery.Where(...) 
関連する問題