C# 寻求LINQ扩展方法帮助
这是迄今为止我遇到的最棘手的问题,我希望有人以前偶然发现了这个问题,并找到了一个优雅的答案。基本上,我有一些linq扩展方法,这些方法恰好是在亚音速下,但适用于任何linq导数,这些linq导数可以完美地扩展。where和。WhereNotIn。这些方法用于将linq转换为中的sql等价物。现在,当提供已知类型的参数(即数组或params数组)时,下面的代码可以完美地工作:C# 寻求LINQ扩展方法帮助,c#,.net,linq,subsonic,C#,.net,Linq,Subsonic,这是迄今为止我遇到的最棘手的问题,我希望有人以前偶然发现了这个问题,并找到了一个优雅的答案。基本上,我有一些linq扩展方法,这些方法恰好是在亚音速下,但适用于任何linq导数,这些linq导数可以完美地扩展。where和。WhereNotIn。这些方法用于将linq转换为中的sql等价物。现在,当提供已知类型的参数(即数组或params数组)时,下面的代码可以完美地工作: public static IQueryable<T> WhereIn<T, TValue>(
public static IQueryable<T> WhereIn<T, TValue>(
this IQueryable<T> query,
Expression<Func<T, TValue>> selector,
params TValue[] collection) where T : class
{
if (selector == null) throw new ArgumentNullException("selector");
if (collection == null) throw new ArgumentNullException("collection");
ParameterExpression p = selector.Parameters.Single();
if (!collection.Any()) return query;
IEnumerable<Expression> equals = collection.Select(value =>
(Expression)Expression.Equal(selector.Body,
Expression.Constant(value, typeof(TValue))));
Expression body = equals.Aggregate(Expression.Or);
return query.Where(Expression.Lambda<Func<T, bool>>(body, p));
}
然而,现在对于复杂的部分。我希望能够将IQueryable对象传递到上面的重载版本中,该重载版本接受第二个linq对象作为参数,以便实现表1中的select*的等效功能,其中table1.id inselect id from table2。以下是方法签名,它实际上编译正常,但缺少所有重要的逻辑:
public static IQueryable<T> WhereIn<T, TValue, T2, TValue2>(
this IQueryable<T> query,
Expression<Func<T, TValue>> selector,
T2 entity2,
Expression<Func<T2, TValue2>> selector2) where T : class
{
if (selector == null) throw new ArgumentNullException("selector");
if (selector2 == null) throw new ArgumentNullException("selector2");
ParameterExpression p = selector.Parameters.Single();
ParameterExpression p2 = selector2.Parameters.Single();
/* this is the missing section */
/* i'd like to see the final select generated as
*
* select * from T where T.selector in(select T2.selector2 from T2)
*/
return null;
// this is just to allow it to compile - proper return value pending
}
我是不是在这里对着一棵不存在的表达树吠叫:--或者这是很有能力做到的
祝你一切顺利,希望如此
jim为什么不直接使用连接
var query = from x in table1
join y in table2 on x.Id equals y.Id
select x;
或者,如果每个x可能有多个y值:
我希望这样的查询能够在SQL数据库中得到很好的优化
或者如果您真的想在以下位置使用:
我可能错过了更大的东西。。。或者,将上述查询转换为扩展方法可能是您想要的:我最终选择了一种扩展方法来实现这一点,但仍然不是100%成功
我将在稍后的某个时候把实际的完整工作代码放在这里,一旦我将其与所有其他选项集成在一起。jon-我不能使用连接语法,因为目前代码“承诺”在表达式树和泛型中操作。然而,你的第三个选择可能会有结果。我将在上面提到的上下文中仔细研究这一点。因此,是的,转换成扩展方法是goal@jim:join语法只相当于调用join方法。我碰巧发现连接在查询表达式形式中比点表示法更容易表达,但您可以将其表达为table1.Jointable2,x=>x.Id,y=>y.Id,x,y=>x,没有任何问题。jon-一个“结束游戏”就是使用您的上述想法,我能够做到这一点:var newJoin=query.Joinentity2,selector,selector2;但显然,这是无效的语法etcIt已经4年了,你有什么代码可以共享吗?如果它不完整,也许这里的其他人可以帮助批评它,直到它工作。嗨,jp-时间过得真可怕。唉,我从来没有为这个问题找到一个有效的解决方案,而是在扩展方法的道路上蹒跚前行,以弥补任何缺陷。如果它诞生的话,它将是一段奇妙的代码!!哦,好吧。。如果出现了适合的东西,我会按照承诺在这里更新。
var bookings = _repository.Find(r => r.BookingID>0)
.WhereIn(x => x.BookingTypeID, new BookingType(), y => y.BookingTypeID);
var query = from x in table1
join y in table2 on x.Id equals y.Id
select x;
var query = from x in table1
join z in table2.Select(y => y.Id).Distinct() on x.Id equals z
select x;
var query = table1.Where(x => table2.Select(y => y.Id).Contains(x.Id));