c# - 如何合并两个成员表达式树?

标签 c# .net linq-to-sql lambda expression-trees

我试图将以下表达式组合成一个表达式:item => item.sub,sub => sub.key 变成 item => item.sub.key。我需要这样做,以便我可以创建一个 OrderBy 方法,该方法将项目选择器单独带到键选择器。这可以使用 OrderBy 上的重载之一并提供一个 IComparer<T> 来完成。 ,但它不会转换为 SQL。

以下是一个方法签名,用于进一步阐明我要实现的目标,以及一个不起作用但应该说明这一点的实现。

    public static IOrderedQueryable<TEntity> OrderBy<TEntity, TSubEntity, TKey>(
        this IQueryable<TEntity> source, 
        Expression<Func<TEntity, TSubEntity>> selectItem, 
        Expression<Func<TSubEntity, TKey>> selectKey)
        where TEntity : class
        where TSubEntity : class 
    {
        var parameterItem = Expression.Parameter(typeof(TEntity), "item");
        ...
        some magic
        ...
        var selector = Expression.Lambda(magic, parameterItem);
        return (IOrderedQueryable<TEntity>)source.Provider.CreateQuery(
            Expression.Call(typeof(Queryable), "OrderBy", new Type[] { source.ElementType, selector.Body.Type },
                 source.Expression, selector
                 ));
    } 

这将被称为:

.OrderBy(item => item.Sub, sub => sub.Key)

这可能吗?有没有更好的办法?我想要一个以这种方式工作的 OrderBy 方法的原因是为了支持适用于许多实体的复杂键选择表达式,尽管它们以不同的方式公开。此外,我知道有一种方法可以使用深层属性的 String 表示来执行此操作,但我正在努力保持它的强类型。

最佳答案

由于这是 LINQ-to-SQL,您通常可以使用 Expression.Invoke 来发挥子表达式的作用。我看看能不能举个例子(update: done)。但是请注意,EF 不支持此功能 - 您需要从头开始重建表达式。我有一些代码可以执行此操作,但是它很长...

表达式代码(使用Invoke)非常简单:

var param = Expression.Parameter(typeof(TEntity), "item");
var item = Expression.Invoke(selectItem, param);
var key = Expression.Invoke(selectKey, item);
var lambda = Expression.Lambda<Func<TEntity, TKey>>(key, param);
return source.OrderBy(lambda);

这是 Northwind 上的示例用法:

using(var ctx = new MyDataContext()) {
    ctx.Log = Console.Out;
    var rows = ctx.Orders.OrderBy(order => order.Customer,
        customer => customer.CompanyName).Take(20).ToArray();
}

使用 TSQL(重新格式化以适合):

SELECT TOP (20) [t0].[OrderID], -- snip
FROM [dbo].[Orders] AS [t0]
LEFT OUTER JOIN [dbo].[Customers] AS [t1]
  ON [t1].[CustomerID] = [t0].[CustomerID]
ORDER BY [t1].[CompanyName]

关于c# - 如何合并两个成员表达式树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/560039/

相关文章:

c# - 使用 webjobs 调用另一个网站的 api

c# - 使用 linq 从键中获取值

c# - OpenHtmlToPdf 访问被 ASP.NET 拒绝

asp.net - 在为变量 'std'分配值之前,先使用它。空引用异常可能在运行时导致

c# - 与 Linq 中的 group by 不同

c# to vb 转换对象初始化

c# - 在 .NET Core 2.0 中使用 COM 对象

.net - InternalsVisibleTo 不适用于托管 C++

sql - Linq to SQL Case WHEN 在 VB.NET 中?

linq - 使用 LINQ to SQL 从存储过程中获取多维结果