我正如此返回IOrderedQueryable<T>
:
response.Data = Expressions
.ApplySorts(request, result)
.Skip(request.Skip)
.Take(request.Take)
.ToList();
这是我的类,其中包含一个返回IOrderedQueryable<T>
的方法。
public static class Expressions
{
public static IOrderedQueryable<T> ApplySorts<T>(
DataRequest request, IQueryable<T> items)
{
var sorts = request.Sort;
if (sorts != null)
{
foreach (var sort in sorts)
{
items = items.OrderBy(sort.Field + " " + sort.Dir);
}
}
return (IOrderedQueryable<T>)items;
}
}
但是在运行时我得到了这个错误:
{&#34;方法&#39; Skip&#39;只支持LINQ to中的排序输入 实体。方法&#39; OrderBy&#39;必须在方法之前调用 &#39;跳过&#39;&#34;}
请注意,目前没有任何种类;但是,ApplySorts<T>()
的返回值仍应返回Skip()
期望的类型,不是吗?
答案 0 :(得分:8)
您需要默认排序。虽然在大多数数据库中,您可以执行TOP
,LIMIT
或BETWEEN
而不进行排序,但确实没有意义(前两个实际适用于{ {1}},但理论是一样的。)
返回行的顺序是 undefined (即使它们通常按插入顺序显示)。因此,您的ORM阻止您在代码中创建错误(即Take
不一致,并且没有真正有意义)。
进一步解释:Skip
没有Skip(10)
没有意义,它在功能上等同于不存在。如果我们没有订购,我们是否跳过10行是无关紧要的。如果你洗牌一副牌,丢弃前10名,然后拿5,是不是只是简单地拿5而不丢弃?在这两种情况下,你都会得到5张随机牌 - 弃牌是无关紧要的。
如果没有提供排序,您应该有一个默认的排序案例。合适的候选人是表的主键。
答案 1 :(得分:0)
使用反射获取T
的键将作为默认排序参数传递,因为SQL不会提供其他方法:
public static IOrderedQueryable<T> ApplySorts<T>(DataRequest request, IQueryable<T> items)
{
var sorts = request.Sort;
var keyProperty = typeof(T).GetProperties().FirstOrDefault(prop =>
prop.IsDefined(typeof(System.ComponentModel.DataAnnotations.KeyAttribute), false));
if (sorts != null)
{
foreach (var sort in sorts)
{
items = items.OrderBy(sort.Field + " " + sort.Dir);
}
}
else
{
items = items.OrderBy(keyProperty.Name); // set a default sort if there are no sorts provided
}
return (IOrderedQueryable<T>)items;
}