如何组合两个成员表达式树?
我正在尝试将以下表达式组合成一个表达式: item => item.sub, sub => sub.key 成为 item => 项目.子键。 我需要这样做,以便我可以创建一个 OrderBy 方法,该方法将项目选择器单独作为键选择器。 这可以使用 OrderBy 上的重载之一并提供 IComparer
来完成,但它不会转换为 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 方法的原因是支持适用于许多实体的复杂键选择表达式,尽管它们以不同的方式公开。 另外,我知道有一种方法可以使用深层属性的字符串表示来做到这一点,但我试图保持它的强类型化。
I'm trying to combine the following expressions into a single expression: item => item.sub, sub => sub.key to become item => item.sub.key. I need to do this so I can create an OrderBy method which takes the item selector separately to the key selector. This can be accomplished using one of the overloads on OrderBy and providing an IComparer<T>
, but it won't translate to SQL.
Following is a method signature to further clarify what I am trying to achive, along with an implementation that doesn't work, but should illustrate the point.
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
));
}
which would be called as:
.OrderBy(item => item.Sub, sub => sub.Key)
Is this possible? Is there a better way? The reason I want an OrderBy method that works this way is to support a complex key selection expression that applies to many entities, though they are exposed in different ways. Also, I'm aware of a way to do this using String representations of deep properties, but I'm trying to keep it strongly typed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我需要同样的东西,所以做了这个小扩展方法:
I needed the same so made this small extension method:
你所拥有的是排序,然后是投影,然后再次排序。
您的方法可能是这样的:
这将由 SQL 执行,但您可能已经注意到,我必须将此处的返回类型更改为 IOrderedQueryable。 你能解决这个问题吗?
What you have there is sotring, followed by projecting and then sorting again.
Your method could be like this:
This will be executed by SQL but as you might have noticed I had to change the return type here to IOrderedQueryable<TSubEntity>. Can you work around that?
由于这是 LINQ-to-SQL,因此您通常可以使用
Expression.Invoke
来发挥子表达式的作用。 我会看看是否可以举一个例子(更新:完成)。 但请注意,EF 不支持这一点 - 您需要从头开始重建表达式。 我有一些代码可以做到这一点,但它相当冗长...表达式代码(使用
Invoke
)非常简单:这是 Northwind 上的示例用法:
使用 TSQL(重新格式化以适合):
Since this is LINQ-to-SQL, you can usually use
Expression.Invoke
to bring a sub-expression into play. I'll see if I can come up with an example (update: done). Note, however, that EF doesn't support this - you'd need to rebuild the expression from scratch. I have some code to do this, but it is quite lengthy...The expression code (using
Invoke
) is quite simple:Here's example usage on Northwind:
With TSQL (reformatted to fit):