views:

360

answers:

1

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?

A: 

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