我有一个DbSet<Items>
集合。
主键是Guid。我不想通过这个主键订购。我想通过名为&#34; Order&#34;。
的可编辑十进制属性进行排序我所拥有的代码非常简单,并且在用户输入&#34; $ top&#34;参数进入请求:
public class ItemsController : ApiController
{
protected DbContext ctx = // ...
// GET api/documents
[EnableQuery()]
public IQueryable<Item> Get()
{
return ctx.Items.OrderBy(o => o.Order).AsQueryable();
}
当用户放置&#34; $ top&#34;在查询字符串中,顺序变得混乱(它可能会强制排序由主键完成,以获得一致的分页结果 - 但是,在我的情况下,这会产生相反的效果,它会阻止我从一致的分页结果)。
我已经尝试将.AsQueryable()
移到查询的前面(.OrderBy(...)
子句之前),我已经尝试了.AsQueryable()
,而我是;用两个AsQueryables等尝试过它。
此表中将有 lot 项目,因此需要通过IQueryable
完成(通过{{1枚举Web服务器上的所有项目)这里不是一个选项)。
到目前为止唯一有效的方法是传递&#34; $ orderby = Order&#34;来自客户,但我不想强迫(似乎很容易忘记)。
1。)我可以做些什么来使IEnumerable
属性的排序成为默认行为吗?
2。)或者失败了,无论如何,无论如何都要欺骗WebApi / OData认为自定义&#34; $ orderby = Order&#34;条款被指定了吗?
答案 0 :(得分:5)
要覆盖默认排序顺序,您需要将EnableQueryAttribute的属性EnsureStableOrdering设置为false,如描述here:
true值表示原始查询应在何时修改 必须保证稳定的排序顺序。假值表示 无需修改查询即可将排序顺序视为稳定。 确保稳定排序顺序的查询提供程序应设置此值 为假。默认值为true。
因此,在您的代码中,更改动作属性,如下所示:
// GET api/documents
[EnableQuery(EnsureStableOrdering = false)]
public IQueryable<Item> Get()
{
return ctx.Items.OrderBy(o => o.Order).AsQueryable();
}
答案 1 :(得分:1)
您可以手动调用控制器中的odata。这应该创建正确的排序IQueryable然后应用$ top和任何其他odata,如$ filter和$ skip。现在你不必返回导致问题的IQueryable,因为实际的查询是在管道中稍后执行的。
public class ItemsController : ApiController
{
protected DbContext ctx = // ...
public IEnumerable<Item> Get(ODataQueryOptions<Item> odata)
{
var collection = ctx.Items.OrderBy(o => o.Order);
if (odata == null)
{
//return a default max size of 100
return collection.Take(100).ToList();
}
var results = odata.ApplyTo(collection.AsQueryable()) as List<Item>;
//still provide a max incase the $top wasn't specified.
//you could check the odata to see if $top is there or not.
return results.Take(100);
}
}
更多信息可在WebApi documentation。
中找到