2009-03-30 9 views
5

配列を持ち、配列の要素をvarcharの任意の場所に持つレコードを返すvarcharに対してLINQクエリを実行したいとします。配列要素のLIKEクエリのLINQ

何かこれは甘いでしょう。

string[] industries = { "airline", "railroad" }

var query = from c in contacts where c.industry.LikeAnyElement(industries) select c

任意のアイデア?

+0

LINQ to SQL、LINQ to Entities、LINQ to Objects? – Lucas

答えて

5

;:上記のクエリのソースとしてToListメソッド()私が知る限り、これを行う最も簡単な方法は、述語を手作業で書くことです。私は以下の例を使用して(それがStartsWithなどのためにも同様に動作します注意してください):

using (var ctx = new NorthwindDataContext()) 
    { 
     ctx.Log = Console.Out; 
     var data = ctx.Customers.WhereTrueForAny(
      s => cust => cust.CompanyName.Contains(s), 
      "a", "de", "s").ToArray(); 
    } 
// ... 
public static class QueryableExt 
{ 
    public static IQueryable<TSource> WhereTrueForAny<TSource, TValue>(
     this IQueryable<TSource> source, 
     Func<TValue, Expression<Func<TSource, bool>>> selector, 
     params TValue[] values) 
    { 
     return source.Where(BuildTrueForAny(selector, values)); 
    } 
    public static Expression<Func<TSource, bool>> BuildTrueForAny<TSource, TValue>(
     Func<TValue, Expression<Func<TSource, bool>>> selector, 
     params TValue[] values) 
    { 
     if (selector == null) throw new ArgumentNullException("selector"); 
     if (values == null) throw new ArgumentNullException("values"); 
     if (values.Length == 0) return x => true; 
     if (values.Length == 1) return selector(values[0]); 

     var param = Expression.Parameter(typeof(TSource), "x"); 
     Expression body = Expression.Invoke(selector(values[0]), param); 
     for (int i = 1; i < values.Length; i++) 
     { 
      body = Expression.OrElse(body, 
       Expression.Invoke(selector(values[i]), param)); 
     } 
     return Expression.Lambda<Func<TSource, bool>>(body, param); 
    } 

} 
+0

ニース!少なくとも10文字。) – Lucas

4
from c in contracts 
where industries.Any(i => i == c.industry) 
select c; 

このようなものです。コレクションのanyメソッドを使用します。残念ながら、LIKEはここあたりとしてSQLにLINQでサポートされていない

+1

これはLINQ to SQLで例外をスローします。それは "産業(産業、産業)を"(産業界を含む) "と表現することができますが、類似の比較を望んでいます。 – Lucas

0

http://msdn.microsoft.com/en-us/library/bb882677.aspx

これを回避するために、あなたはあなたが使用したいパラメーターを受け入れますストアドプロシージャを記述する必要があります同様のステートメントを呼び出して、LINQからSQLに呼び出します。


ここで注意しなければならないのは、Containsを使用することです。これは、文字列全体が配列要素と一致するかどうかを調べるためには機能しません。何のために見ていることは何か、フィールド自体に含まれる配列要素のためである:クラークはコメントで述べたように

industry LIKE '%<element>%' 

、あなたは変換すべき(各要素に対してIndexOfメソッドへの呼び出しを使用することができますSQLコールへ):

string[] industries = { "airline", "railroad" } 

var query = 
    from c in contacts 
    where 
     c.industry.IndexOf(industries[0]) != -1 || 
     c.industry.IndexOf(industries[1]) != -1 

配列の長さと要素の数を知っていれば、これをハードコードすることができます。そうでない場合は、配列と見ているフィールドに基づいてExpressionインスタンスを作成する必要があります。

+0

私はそれを知っていた..私の悪い.. charindex!= -1配列内の各項目についてはうまくいくだろう。 – Clark

+1

実際にLIKEはLINQ to SQLで多少サポートされています。 "航空会社"はどこにあるのですか? "航空会社"とは何ですか?しかし、彼は1つではなく、与えられた価値のいずれかを望みます。 – Lucas

3

IEnumerable.Contains()は、のようにでSQL に変換:

WHERE 'american airlines' IN ('airline', 'railroad') -- FALSE 

String.Contains()%ようなSQL に変換され...%のように:

WHERE 'american airlines' LIKE '%airline%' -- TRUE 

あなたは、連絡先場所たい場合連絡先の業界は、任意の業種のいずれかを好きなので、Any()とString.Contains()を次のようなものに組み合わせたい:

string[] industries = { "airline", "railroad" }; 

var query = from c in contacts 
      where industries.Any(i => c.Industry.Contains(i)) 
      select c; 

しかし、このように両方の任意の()とString.Contains()を組み合わせることで、SQLにLINQでサポートませです。連絡先のセットが十分に小さい場合は、DBからそれらのすべてを持って来ることができる、(通常はお勧めしませんが)

where c.Industry.Contains("airline") || 
     c.Industry.Contains("railroad") || ... 

かとフィルタを適用します。与えられた産業のセットが小さい場合には、あなたのような何かを試すことができますcontacts.AsEnumerable()またはcontactsを使用して、LINQ to Objectsを使用します。これは、通常のLINQで行うことは困難である何かのために、実際に私は私の「Express Yourself」プレゼンテーションで使う例です

var query = from c in contacts.AsEnumerable() 
      where industries.Any(i => c.Industry.Contains(i)) 
      select c; 
1
次のようにクエリを構築する場合、それが動作します

VARクエリをcontacts.AsEnumerableにCから=() select c;

query = query.Where(c =>(c.Industry.Contains( "airline"))||(c.Industry.Contains( "railroad")));

パラメータ航空会社と鉄道がユーザー入力の場合は、上記の文字列をプログラムで生成するだけで済みます。これは実際に私が予想していたよりも少し複雑でした。記事を参照してください - http://www.albahari.com/nutshell/predicatebuilder.aspx