2009-11-10 50 views
22

このLINQ To SQLクエリを検討してください。それは意図なのは[]の検索語の文字列を取り、SQLテーブルに異なるフィールドの束に条件を適用することです:LINQ To SQL例外:Contains演算子以外のクエリ演算子のLINQ to SQL実装でローカルシーケンスを使用できません

string[] searchTerms = new string[] {"hello","world","foo"}; 
List<Cust> = db.Custs.Where(c => 
    searchTerms.Any(st => st.Equals(c.Email)) 
|| searchTerms.Any(st => st.Equals(c.FirstName)) 
|| searchTerms.Any(st => st.Equals(c.LastName)) 
|| searchTerms.Any(st => st.Equals(c.City)) 
|| searchTerms.Any(st => st.Equals(c.Postal)) 
|| searchTerms.Any(st => st.Equals(c.Phone)) 
|| searchTerms.Any(st => c.AddressLine1.Contains(st)) 
) 
.ToList(); 

例外が発生します

ローカルシーケンスを使用することはできませんLINQで含まれています()演算子を除き、クエリ演算子のSQL実装に

質問: はなぜ、この例外が発生し、どのようにクエリがrewrittすることができますこの例外を回避するには?

答えて

32

クエリのAny with Containsの使用法を置き換えます。例:

searchTerms.Contains(c.Email) 

これは、あなたが探している結果を得るはずです。それは後方に向いていますが、それは正しいです。それは、Contains内の各フィールドに対して、searchTermsのすべての要素を持つIN演算子を生成します。

住所1の部分は、あなたが

c.addressLine1.Contains(...) 

との比較を自分で-生成するループにPredicateBuilderような何かが、このために役立つことがありますway-これを動作しません。

+0

@nitzmahone:ありがとう、PredicateBuilderをチェックします。有望! –

+0

私はLinqToSqlの実装では、条件のいくつかがLinqToSqlプロバイダによって実装されていないことがあるので、 'PredicateBuilder'のawesomenessが失望することに懸念します。 –

+0

+1 '.Contains()' - LinqToSqlでサポートされていない方程式の良い代替品です。 'PredicateBuilder'はオプションであっても注意が必要です。 –

11

だけの思考(直接の質問に関連するが、それは他の視聴者を助けるかもしれません):

私は私が正しく含まれています()メソッドを使用していたにも関わらず、あなたと同じエラーメッセージを取得し、されました私の問題の根本がIEnumerableをL2Sクエリーの結果をさらにフィルタリングするために必要なものに戻していたことがわかりました。関数の戻り値の型をIQueryableに変更すると、問題はなくなりました。 IEnumerableをさらにフィルタリングすることはできませんが、IQueryableではこれを行うことができます。

0

同じエラーが発生しましたが、上記の解決策のどれも私のために働いていませんでした。それが働いた理由

List<Cust> =db.Custs.ToList<Cust>.Where(... 

私はわかりませんが、それはやった:私のために働いた何

ように、リスト最初db.Custsをキャストすることでした。

+3

'Contains()'拡張メソッドをSQLに変換するのではなく、データベースをバイパスしてコレクションに対して作業しているので、あなたのケースで動作します。 –

0

本質的に、エラーは、2つのコレクション間で結合を実行しているというエラーです。そのうちの1つはデータベーステーブルであり、もう1つは配列です。 LINQはそれを処理するようには設計されていません - データベース内にあるか、両方のメモリ内にある必要があります(Containsを使用すると特別な例外があります)