LINQ是可组合的,但要做到这一点,而不使用UNION,你必须推出自己的Expression
。基本上,我们(可能)想要创建以下格式的TSQL:
SELECT *
FROM [table]
WHERE (Name = @name1 AND Amount <= @amount1)
OR (Name = @name2 AND Amount <= @amount2)
OR (Name = @name3 AND Amount <= @amount3)
...
其中名称/数量对在运行时确定。在LINQ中有简单的措辞方式;如果每次都是“AND”,我们可以重复使用.Where(...)
。 Union
是一个候选人,但我已经看到重复的人遇到问题。我们想要做的是模仿我们写一个LINQ查询,如:
var qry = from i in db.Ingredients
where ( (i.Name == name1 && i.Amount <= amount1)
|| (i.Name == name2 && i.Amount <= amount2)
...)
select i;
这是通过制定一个Expression
完成,使用Expression.OrElse
每个组合 - 所以我们需要遍历我们的名字/量对,使得更丰富Expression
。
写作Expression
手写的代码是一种黑色艺术,但我有一个非常类似的例子(从我给出的演示文稿);它使用一些自定义的扩展方法;使用方法如下:
IQueryable query = db.Ingredients.WhereTrueForAny(
localIngredient => dbIngredient =>
dbIngredient.Name == localIngredient.Name
&& dbIngredient.Amount <= localIngredient.Amount
, args);
其中args
是您测试成分的数组。它的作用是:对于args
(我们当地的测试成分阵列)localIngredient
中的每个localIngredient
,它要求我们提供一个(对于localIngredient
),该测试适用于数据库。然后将其与Expression.OrElse
结合这些(反过来):
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 there are no filters, return nothing
if (values.Length == 0) return x => false;
// if there is 1 filter, use it directly
if (values.Length == 1) return selector(values[0]);
var param = Expression.Parameter(typeof(TSource), "x");
// start with the first filter
Expression body = Expression.Invoke(selector(values[0]), param);
for (int i = 1; i < values.Length; i++)
{ // for 2nd, 3rd, etc - use OrElse for that filter
body = Expression.OrElse(body,
Expression.Invoke(selector(values[i]), param));
}
return Expression.Lambda<Func<TSource, bool>>(body, param);
}
我原本以为Linq可以处理加入两种类型的实体,直到我试过它 – cjk 2009-04-08 13:08:14
你想得到什么结果?我真的不明白,“查询我的ingredientsList对我的”成分“表”部分。 – antonioh 2009-04-08 13:20:49