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