【问题标题】:How to implement outer join expression tree?如何实现外连接表达式树?
【发布时间】:2010-10-28 03:04:08
【问题描述】:

我需要使用表达式语法来实现查询(因为我不知道编译时的类型)。例如这样的查询:

from customer in Customers
join purchase in Purchases
    on customer.ID equals purchase.CustomerID
into outerJoin
from range in outerJoin.DefaultIfEmpty()
where 
    customer.Name == "SomeName" && 
    range.Description.Contains("SomeString") &&
    customer.ID == range.CustomerID
select 
    new { Customer = customer, Purchase = range }

我找到了像这样实现组加入部分的方法:

ITable p = _dataContext.GetTable(typeof(Purchases));
ITable c = _dataContext.GetTable(typeof(Customers));

LambdaExpression outerSelectorLambda    = DynamicExpression.ParseLambda(typeof(Customers), null, "ID");
LambdaExpression innerSelectorLambda    = DynamicExpression.ParseLambda(typeof(Purchases), null, "CustomerID");

ParameterExpression param1 = Expression.Parameter(typeof(Customers), "customer");
ParameterExpression param2 = Expression.Parameter(typeof(IEnumerable<Purchases>), "purchases");

ParameterExpression[] parameters = new ParameterExpression[] { param1, param2 };

LambdaExpression resultsSelectorLambda = DynamicExpression.ParseLambda(parameters, null, "New(customers as customers, purchases as purchases)");

MethodCallExpression joinCall = 
 Expression.Call(
   typeof(Queryable),
   "GroupJoin",
   new Type[] { 
      typeof(Customers), 
      typeof(Purchases), 
      outerSelectorLambda.Body.Type, 
      resultsSelectorLambda.Body.Type 
   },
   c.Expression,
   p.Expression,
   Expression.Quote(outerSelectorLambda),
   Expression.Quote(innerSelectorLambda),
   Expression.Quote(resultsSelectorLambda)
);

但我不知道如何使用这种语法编写查询的其余部分。 有没有人可以帮帮我?

【问题讨论】:

    标签: linq join lambda expression outer-join


    【解决方案1】:

    我刚刚复制并粘贴了 dynamic.cs 中的“join”实现,并进行了一些更改以使“GroupJoin”能够正常工作。

    public static IQueryable GroupJoin(this IQueryable outer, IEnumerable inner, string outerSelector, string innerSelector, string resultsSelector, params object[] values)
    {
        if (inner == null) throw new ArgumentNullException("inner");
        if (outerSelector == null) throw new ArgumentNullException("outerSelector");
        if (innerSelector == null) throw new ArgumentNullException("innerSelector");
        if (resultsSelector == null) throw new ArgumentNullException("resultsSelctor");
    
        LambdaExpression outerSelectorLambda = DynamicExpression.ParseLambda(outer.ElementType, null, outerSelector, values);
        LambdaExpression innerSelectorLambda = DynamicExpression.ParseLambda(inner.AsQueryable().ElementType, null, innerSelector, values);
    
        Type resultType = typeof(IEnumerable<>).MakeGenericType(inner.AsQueryable().ElementType);
    
        ParameterExpression[] parameters = new ParameterExpression[]
        {
            Expression.Parameter(outer.ElementType, "outer"), Expression.Parameter(resultType, "inner")
        };
        LambdaExpression resultsSelectorLambda = DynamicExpression.ParseLambda(parameters, null, resultsSelector, values);
    
        return outer.Provider.CreateQuery(
                   Expression.Call(
                       typeof(Queryable), "GroupJoin",
                       new Type[] { outer.ElementType, inner.AsQueryable().ElementType, outerSelectorLambda.Body.Type, resultsSelectorLambda.Body.Type },
                       outer.Expression, inner.AsQueryable().Expression, Expression.Quote(outerSelectorLambda), Expression.Quote(innerSelectorLambda), Expression.Quote(resultsSelectorLambda)));
    }
    

    【讨论】:

      【解决方案2】:

      我会采用一种方法来实现这一目标:

      1. 获取与 LINQ 查询等效的表达式。

      2. 获取从 LINQ 查询中提取的表达式的 ToString()。

      3. 研究Expression,了解输入参数、类型参数、Expression Arguments等...

      如果提到的方法不清楚,请回复我。

      【讨论】:

        猜你喜欢
        • 2017-09-22
        • 2023-03-28
        • 1970-01-01
        • 2021-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-10
        • 2016-06-26
        相关资源
        最近更新 更多