C# 寻求LINQ扩展方法帮助

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>(

这是迄今为止我遇到的最棘手的问题,我希望有人以前偶然发现了这个问题,并找到了一个优雅的答案。基本上,我有一些linq扩展方法,这些方法恰好是在亚音速下,但适用于任何linq导数,这些linq导数可以完美地扩展。where和。WhereNotIn。这些方法用于将linq转换为中的sql等价物。现在,当提供已知类型的参数(即数组或params数组)时,下面的代码可以完美地工作:

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));