我正在构建一个Linq表达式,我没有能力在这个项目中使用Dynamic 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);
我已经看过帖子的错误是我需要明确列出<TSource, TKey>
,但由于连接语法的复杂性,我不知道如何明确列出这些。我尝试了<Order, string>
,但无效。
一切都有帮助,谢谢。
答案 0 :(得分:1)
因为你忘记写出你想要达到的目标(没有规范),所以你的问题是什么以及如何解决这个问题有点不清楚。我假设您的问题不是连接(尽管可以简化),但问题是您的方法的用户如何提供排序属性。
如何指定和使用排序属性
问题是,函数的调用者决定了sort属性。当然你只想制作有用且非常可重复使用的函数,所以你不想限制函数的用户,他可以指定他想要的任何排序属性,只要它是你的连接的结果可以被排序的东西上。
您的加入结果包含来自Orders
和Sequence
成员序列的数据。很明显,您的用户只能请求对来自Orders
和/或Members
的值(的组合)的加入结果进行排序。
Queryable.OrderBy
中的键选择器格式为Expression<Func<TSource, TKey>> keySelector
。在这种格式中,TSource是您加入的结果。
由于用户只能对来自Orders
和/或Members
的值进行排序,因此其密钥选择器应该是从Orders
和/或{{1}中选择密钥的函数}
Members
用法示例如下:
public MyResult MyQuery<TKey>(Expression<Func<Order, Member, TKey> keySelector,
SortOrder sortOrder)
{
... // TODO: your query?
}
现在指定了接口,让我们定义一些辅助类并填充你的函数
// order by Order.Id:
var result = MyQuery( (order, member) => order.Id, SortOrder.Ascending);
// order by Member.Name:
var result = MyQuery( (order, member) => member.Name, SortOrder.Descending);
// order by something complicated
var result = MyQuery( (order, member) => new{Id = order.Id, Name = member.Name},
SortOrder.Ascending);
我所做的是,您的原始结果是放在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
的值,并将SortKey
和SortKey
放在MyResult
中。
您是否注意到Expression的返回值是TKey,它也是SortKey属性的类型?
因为我已经定义了辅助类,所以我的编译器可以检查我没有出错。
进行排序:
SortableMyResult
最后,提取并返回MyResult:
IQueryable<SortableMyResult<TKey>> sortedMyResult;
switch (sortOrder)
{
case sortOrder.Ascending:
sortedMyResult = query.OrderBy(item => item.SortKey);
break;
case sortOrder.Descending:
sortedMyResult = query.OrderByDescending(item => item.SortKey);
break;
default: // do not order
sortedMyResult = query;
break;
}
如果你想让你的函数更通用,你可以让调用者提供return sortedMyResult.Select(sortedMyResult => sortedMyResult.MyResult);
的机会(如果他没有,则使用IComparer
的默认比较器):
TKey
答案 1 :(得分:0)
感谢您提供令人难以置信的详细答案。现在已经有几个月了,关于MVC和现有应用程序代码的更多内容正在变得清晰。在我的案例中发生的事情是我们定义了一个扩展方法,它允许OrderBy和OrderByDescending接受我们的排序模块从前端传入的字符串。例如:
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string propertyName)
{
return GetExpression(source, propertyName);
}
然后,它会将其汇总到一个返回IOrderedQueryable<T>
我没有包含对此的引用,由于我对框架和应用程序的经验不足,我基本上没有理由摇头。