Entity framework 具有联接和条件OrderBy/OrderByDescending的Linq表达式

Entity framework 具有联接和条件OrderBy/OrderByDescending的Linq表达式,entity-framework,linq,linq-to-sql,asp.net-mvc-5,Entity Framework,Linq,Linq To Sql,Asp.net Mvc 5,我正在构建一个Linq表达式,我没有能力在这个项目中使用动态Linq。这是我的初步声明 var orderListQuery = context.Orders.Where(oExpr) .Join(context.Members, o => o.MemberId, m => m.Id,

我正在构建一个Linq表达式,我没有能力在这个项目中使用动态Linq。这是我的初步声明

                   var orderListQuery = context.Orders.Where(oExpr)
                        .Join(context.Members,
                            o => o.MemberId,
                            m => m.Id,
                            (o, m) => new {Order = o, Member = m})
                        .Where(oM => oM.Member.CustomerId == custId);
下一部分是我想有条件地添加一个降序表达式:

                orderListQuery = descending
                    ? orderListQuery.OrderByDescending(sortProperty)
                    : orderListQuery.OrderBy(sortProperty);
我在文章中看到的错误是,我需要显式列出
,但由于连接语法的复杂性,我不知道如何显式列出这些。我尝试了
,但不起作用


任何有帮助的,谢谢。

因为你忘了写下你想要达到的目标(没有具体说明),所以有点不清楚你的问题是什么,以及如何解决。我假设您的问题不是连接(尽管可以简化),而是方法的用户如何提供排序属性

如何指定和使用排序属性

问题是,函数的调用方决定排序属性。当然,您只想创建有用且可重用的函数,因此您不想限制函数的用户,他可以指定他想要的任何排序属性,只要它是可以对联接结果进行排序的属性

联接的结果包含来自
订单序列
成员序列
的数据。很明显,您的用户只能请求根据
订单
和/或
成员
中的值(组合)对您的加入结果进行排序

Queryable.OrderBy
中的键选择器的格式为
Expression keySelector
。在这种格式中,TSource是您加入的结果

由于用户只能对
订单
和/或
成员
中的值进行排序,因此他的键选择器应该是从
订单
和/或
成员
中选择键的功能

public MyResult MyQuery<TKey>(Expression<Func<Order, Member, TKey> keySelector,
    SortOrder sortOrder)
{
    ... // TODO: your query?
}
现在指定了接口,让我们定义一些帮助器类并填充函数

class MyResult
{
    public Order Order {get; set;}
    public Member Member {get; set;}
}

class SortableMyResult<TKey>
{
    public TKey SortKey {get; set;}
    public MyResult MyResult {get; set;}
}

MyResult MyQuery<TKey>(
    Expression<Func<Order, Member, TKey> keySelector, SortOrder sortOrder)
{
    var query = context.Orders.Where(oExpr)
        .Join(context.Members,
            order => order.MemberId,
            member => member.Id,
            (order, member) => new SortableMyResult<TKey>()
            {
                SortKey = KeySelector(order, member),
                MyResult = new MyResult()
                {
                    Order = order,
                    Member = member,
                 }
            ))
            .Where(....);
最后,提取并返回MyResult:

return sortedMyResult.Select(sortedMyResult => sortedMyResult.MyResult);
如果您想使您的函数更通用,可以让调用者提供一个
i比较程序
(如果他不提供,则使用
TKey的默认比较程序
):

MyResult MyQuery(

Expression感谢您提供了令人难以置信的详细答案。几个月过去了,关于MVC和现有应用程序代码的更多信息变得清晰起来。在我的例子中,我们定义了一个扩展方法,允许OrderBy和OrderByDescending接受排序模块从前端传入的字符串。e。g:

    public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string propertyName)
    {
        return GetExpression(source, propertyName);
    }
公共静态IOrderedQueryable OrderByDescending(此IQueryable源,字符串propertyName)
{
返回GetExpression(源,propertyName);
}
然后将其导入一个GetExpression函数,该函数返回一个
IOrderedQueryable


我没有提到这一点,由于我对框架和应用程序都缺乏经验,所以我毫无理由地绞尽脑汁。

你需要构造一个指向你的属性的表达式。但是如果你只描述一下你试图用这段代码实现什么,那会更好,因为有pr可能更容易做到这一点:成员Id与客户Id不同,客户Id不在订单上。但是,成员Id和客户Id是成员表的一部分。(遗留代码问题)我正在尝试按客户Id获取所有订单,并根据视图中作为操作请求发送的sortProperty对其进行排序。(例如,按日期排序、小计等)。在这种情况下,sortProperty始终是一个字符串。因此,
sortProperty
是一个包含属性名的
字符串?@MichaelSefranek所以为什么不设置外键,然后正常地获取数据呢?从链接中获取类,然后使用
.OrderByMember(“Order.+sortProperty”)
。类似于降序。
return sortedMyResult.Select(sortedMyResult => sortedMyResult.MyResult);
MyResult MyQuery<TKey>(
    Expression<Func<Order, Member, TKey> keySelector,
    SortOrder sortOrder,
    IComparer<TKey> comparer = EqualityComparer<TKey>.Default)
{
    ...
}
    public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string propertyName)
    {
        return GetExpression(source, propertyName);
    }