2009-05-22 2 views
0

Мне нужно реализовать запрос, используя синтаксис выражений (потому что во время компиляции я не знаю типов). Например, запрос, как этот:Как реализовать внешнее дерево выражений объединения?

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

Но я не могу понять, как написать остальную часть запроса, используя следующий синтаксис , Кто-нибудь может мне помочь?

ответ

0

Я просто скопировал + вставлял реализацию «join» в dynamic.cs и сделал пару изменений, чтобы заставить «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))); 
} 
0

я последую подход для достижения этой цели:

  1. Получить Expression эквивалент запроса LINQ.

  2. Получите выражение ToString(), извлеченное из запроса LINQ.

  3. Исследование Экспрессия, чтобы понять входные параметры, параметры типа, выражения Аргументы и т.д. ...

Вернись ко мне, если подход упоминается не ясно.