このLINQToSQLクエリについて考えてみます。検索用語のstring []を取得し、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();
例外が発生します:
ローカルシーケンスは、Contains()演算子を除くクエリ演算子のLINQ toSQL実装では使用できません。
質問:なぜこの例外が発生するのですか?また、この例外を回避するためにクエリをどのように書き直すことができますか?
クエリでAnyの使用法をContainsに置き換えます。例えば:
searchTerms.Contains(c.Email)
これはあなたが探している結果を得るはずです。後ろ向きに見えますが、正しいです。searchTermsのすべての要素を含むContains内の各フィールドに対してIN演算子が生成されます。
AddressLine1の部分はこのようには機能しません。ループで比較を生成する必要があります。
c.addressLine1.Contains(...)
PredicateBuilder のようなものがこれに役立ちます。
ただの考え(質問に直接関係していませんが、他の視聴者に役立つかもしれません):
正しくContains()メソッドを使用していても、同じエラーメッセージが表示され、問題の原因がIEnumerableを、さらにフィルタリングする必要のあるものに返すことであることがわかるまでにかなりの時間がかかりました。 L2Sクエリの結果。関数の戻り値の型をIQueryableに変更すると、問題は解決しました。 IEnumerableをさらにフィルタリングすることはできませんが、IQueryableはフィルタリングできることを考えると、それは理にかなっています。
同じエラーが発生しましたが、上記の解決策はどれもうまくいきませんでした。
私のために働いたのは、db.Custs
をリストにキャストすることでした最初の、次のように:
List<Cust> =db.Custs.ToList<Cust>.Where(...
なぜ機能したのかわかりませんが、機能しました。
基本的に、エラーは、2つのコレクション間で結合を行っていることを示しています。1つはデータベーステーブルで、もう1つは配列です。 LINQはそれを処理するようには設計されていません-両方がデータベースにあるか、両方がメモリ内にある必要があります(Contains
を使用する場合の特別な場合の例外を除く)