【问题标题】:Entity Framework: combining paging with Dynamic LINQ OrderBy实体框架:将分页与动态 LINQ OrderBy 相结合
【发布时间】: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&lt;Item&gt;,但 Dynamic LINQ OrderBy 没有过载,它返回 IOrderedQueryable&lt;T&gt;。 如果我将排序和页面代码提取到相同的方法中,使用var 不再是问题,它会推断类型。问题似乎是在排序和分页时使用IQueryable 接口。有没有办法可以将此逻辑分解为单独的方法,但仍使用动态 LINQ 进行排序?

非常感谢任何帮助。

【问题讨论】:

  • 这个问题要小得多。就目前而言,Sort 方法没有效果(Page 和任何 LINQ 方法也是如此),因为您没有使用应用的可查询运算符返回结果。考虑将它们更改为返回 IQueryable&lt;Item&gt; 的方法,例如private IQueryable&lt;Item&gt; Sort(...) { return items.OrderBy(...); }。我也不要忘记使用返回的结果。
  • @IvanStoev 该方法无效,但我将项目作为参考传递,不是吗?我将项目设置为扩展可查询。也许我很困惑?
  • 您将对对象的引用传递给项目(这是您方法中的局部变量)。然后您更改项目(仍然是局部变量),然后您的方法结束。要实现您想要的(= 更改外部items),您需要使用ref IQueryable&lt;Item&gt; items,或者您需要返回局部变量items。使用return ... 是迄今为止最常见的方法。
  • 是的,您将它们作为参考传递。但所有 LINQ 方法都不会修改 IQueryable 引用。相反,它们返回需要使用的 new 引用。如果您的意思是在 void 方法中分配 items 变量,您可以考虑阅读 C# 中的 ref 参数。
  • 是的,你很困惑。您的排序功能不会对您进行排序,它只会用新查询替换变量项。由于 your4 变量既不是 ref 也不是 out,调用者提供的 items 对象不会改变。如果您不替换可变项,而是更改了项的属性,那将是不同的

标签: c# entity-framework linq dynamic-linq


【解决方案1】:

您应该从 Sort() 和 Page() 方法返回新构造的 IQueryable,就像对 GetItems() 所做的那样。 如果你在这样的方法中“重写”一个参数值,它对最初传递给参数的值没有影响,因为 C# 使用按值参数传递语义

更多参考请参见: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters

【讨论】:

  • 我将项目作为对 Sort 和 Page 方法的引用传递,或者我很困惑?
  • 确实IQueryable是一个接口,所以它是一个引用类型,但是你不是通过引用传入参数。两者是不相关的:您可以通过值传递引用类型(默认语义),也可以通过引用来传递。您正在按值传递引用类型(基本上是内存地址)(因此分配了一个新块并复制了引用,但在您进行分配时旧的块保持不变)。有关详细信息,请参阅此文档示例:docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-25
  • 1970-01-01
  • 1970-01-01
  • 2017-09-15
  • 2017-07-07
  • 2018-10-30
相关资源
最近更新 更多