以下是示例代码:
``` string[] industries = { "airline", "railroad" }; var query = from c in contacts where industries.Any(i => c.industry.Contains(i)) select c; ```
这实际上是我在我的“表达自己”演示中使用的一个例子,用于说明在常规LINQ中难以实现的内容;据我所知,最简单的方法是手动编写谓词。我使用下面的示例(请注意,它同样适用于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);
}
}
from c in contracts
where industries.Any(i => i == c.industry)
select c;
类似这样的。在集合上使用任何方法。
IEnumerable.Contains()
被翻译为SQL语句中的IN,如下所示:
WHERE 'american airlines' IN ('airline', 'railroad') -- FALSE
String.Contains()
翻译成 SQL LIKE %...%,例如:
WHERE 'american airlines' LIKE '%airline%' -- TRUE
string[] industries = { "airline", "railroad" };
var query = from c in contacts
where industries.Any(i => c.Industry.Contains(i))
select c;
然而,在LINQ to SQL中,将Any()和String.Contains()结合起来使用是不被支持的。如果给定的行业集较小,你可以尝试以下方法:
where c.Industry.Contains("airline") ||
c.Industry.Contains("railroad") || ...
或者(虽然通常不建议这样做),如果联系人集合足够小,您可以从数据库中将它们全部提取出来,并使用 contacts.AsEnumerable() 或 contacts.ToList() 作为上述查询的数据源来应用 LINQ to Objects 进行过滤:
var query = from c in contacts.AsEnumerable()
where industries.Any(i => c.Industry.Contains(i))
select c;
如果您按照以下方式构建查询,它将起作用:
var query = from c in contacts.AsEnumerable() select c;
query = query.Where(c=> (c.Industry.Contains("airline")) || (c.Industry.Contains("railroad")));
如果航空公司和铁路公司是用户输入的参数,则只需以编程方式生成上述字符串即可。实际上,这比我预期的要复杂一些。请参阅文章 - http://www.albahari.com/nutshell/predicatebuilder.aspx
很遗憾,根据这里,LIKE在LINQ to SQL中不受支持:
http://msdn.microsoft.com/en-us/library/bb882677.aspx
为了解决这个问题,您需要编写一个存储过程,该存储过程将接受您想要在like语句中使用的参数,并从LINQ to SQL中调用它。industry LIKE '%<element>%'
string[] industries = { "airline", "railroad" }
var query =
from c in contacts
where
c.industry.IndexOf(industries[0]) != -1 ||
c.industry.IndexOf(industries[1]) != -1