【发布时间】:2017-09-11 10:59:56
【问题描述】:
我正在使用实体框架检索一些数据,如下所示:
var items = GetItems(storeNumber);
Sort(items);
Page(items);
return await items.ToListAsync();
我有这些私有辅助方法:
private IQueryable<Item> GetItems(string storeNumber)
{
return _dbContext.Items.Where(x => x.StoreNumber == storeNumber);
}
我使用动态 LINQ 对结果进行排序。
private void Sort(IQueryable<Item> items, string fieldToSort, string sortDirection)
{
items = items.OrderBy($"{fieldToSort} {sortDirection}");
}
在我的 Page 方法中我得到了异常
方法“OrderBy”必须在方法“Skip”之前调用
private void Page(IQueryable<Item> items, int skip, int take)
{
items = items.Skip(skip).Take(take);
}
我怀疑错误的原因是因为 items 需要是 IOrderedQueryable<Item>,但 Dynamic LINQ OrderBy 没有过载,它返回 IOrderedQueryable<T>。
如果我将排序和页面代码提取到相同的方法中,使用var 不再是问题,它会推断类型。问题似乎是在排序和分页时使用IQueryable 接口。有没有办法可以将此逻辑分解为单独的方法,但仍使用动态 LINQ 进行排序?
非常感谢任何帮助。
【问题讨论】:
-
这个问题要小得多。就目前而言,
Sort方法没有效果(Page和任何 LINQ 方法也是如此),因为您没有使用应用的可查询运算符返回结果。考虑将它们更改为返回IQueryable<Item>的方法,例如private IQueryable<Item> Sort(...) { return items.OrderBy(...); }。我也不要忘记使用返回的结果。 -
@IvanStoev 该方法无效,但我将项目作为参考传递,不是吗?我将项目设置为扩展可查询。也许我很困惑?
-
您将对对象的引用传递给项目(这是您方法中的局部变量)。然后您更改项目(仍然是局部变量),然后您的方法结束。要实现您想要的(= 更改外部items),您需要使用
ref IQueryable<Item> items,或者您需要返回局部变量items。使用return ...是迄今为止最常见的方法。 -
是的,您将它们作为参考传递。但所有 LINQ 方法都不会修改
IQueryable引用。相反,它们返回需要使用的 new 引用。如果您的意思是在void方法中分配items变量,您可以考虑阅读 C# 中的ref参数。 -
是的,你很困惑。您的排序功能不会对您进行排序,它只会用新查询替换变量项。由于 your4 变量既不是 ref 也不是 out,调用者提供的 items 对象不会改变。如果您不替换可变项,而是更改了项的属性,那将是不同的
标签: c# entity-framework linq dynamic-linq