How to implement outer join expression tree?

匆匆过客 提交于 2019-12-12 01:17:06

问题


I need to implement the query using expressions syntax (because I don't know types in compile time). For example query like this one:

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 }

I found way to implement group join part like this:

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

But I can't figure out how to write rest of query using this syntax. Does anyone can help me?


回答1:


I would follow an approach to achieve that:

  1. Get the Expression equivalent of the LINQ query.

  2. Get the ToString() of the Expression extracted from the LINQ query.

  3. Study the Expression, to understand the input parameters, type parameters, Expression Arguments etc...

Get back to me if the approach mentioned is not clear.




回答2:


I just copied + pasted the "join" implementation in dynamic.cs and made couple of changes to make "GroupJoin" to work.

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


来源:https://stackoverflow.com/questions/896204/how-to-implement-outer-join-expression-tree

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!