配列を持ち、配列の要素をvarcharの任意の場所に持つレコードを返すvarcharに対してLINQクエリを実行したいとします。配列要素のLIKEクエリのLINQ
何かこれは甘いでしょう。
string[] industries = { "airline", "railroad" }
var query = from c in contacts where c.industry.LikeAnyElement(industries) select c
任意のアイデア?
配列を持ち、配列の要素をvarcharの任意の場所に持つレコードを返すvarcharに対してLINQクエリを実行したいとします。配列要素のLIKEクエリのLINQ
何かこれは甘いでしょう。
string[] industries = { "airline", "railroad" }
var query = from c in contacts where c.industry.LikeAnyElement(industries) select c
任意のアイデア?
;:上記のクエリのソースとして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);
}
}
ニース!少なくとも10文字。) – Lucas
from c in contracts
where industries.Any(i => i == c.industry)
select c;
このようなものです。コレクションのanyメソッドを使用します。残念ながら、LIKEはここあたりとしてSQLにLINQでサポートされていない
これはLINQ to SQLで例外をスローします。それは "産業(産業、産業)を"(産業界を含む) "と表現することができますが、類似の比較を望んでいます。 – Lucas
:
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インスタンスを作成する必要があります。
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;
:
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
LINQ to SQL、LINQ to Entities、LINQ to Objects? – Lucas