如何实现外连接表达式树?

发布于 2024-07-20 06:10:21 字数 1747 浏览 3 评论 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)
);

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

黑寡妇 2024-07-27 06:10:21

我将遵循一种方法来实现这一目标:

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

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

  3. 研究表达式,了解输入参数、类型参数、表达式参数等...

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

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.

草莓味的萝莉 2024-07-27 06:10:21

我刚刚在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)));
}

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)));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文