【问题标题】:How can i create pagination properly with List<IGrouping<string,Product>>?如何使用 List<IGrouping<string,Product>> 正确创建分页?
【发布时间】:2017-12-21 23:24:35
【问题描述】:

我有这个查询,它通过 UniqueGroupId 对所有项目进行分组

result = ProductList1.Except(productlist3).Union(ProductList2).GroupBy(a => a.UniqueGroupId).OrderByDescending(a=>a.Key).ToList();

它返回一个List&lt;IGrouping&lt;string,Product&gt;&gt;

它工作正常,每个产品都正确分组,当它找到一个没有设置 UniqueGroupId 的元素时,它会返回一个带有 null 键的巨型组,其中包含所有没有设置正确 UniqueGroupId 的产品。

然后将此查询结果提供给显示内容的视图。

现在,由于结果越来越大,我想实现分页以更好地显示内容,其中每个组都被计为页面的 1 个元素,除了 Key 为 null 的组,在此,每个元素该组应被视为 1 个元素。

我想使用 Skip 和 Take,但显然问题是如果我 Skip(50) 也跳过 Key null 中包含的所有元素,这不是我想要实现的..

我该如何解决这个问题?谢谢

【问题讨论】:

  • 视图如何显示结果?视图是否采用分组元素,然后在显示之前将其展平?
  • 所涉及的ProductList变量是否在内存集合中(例如List&lt;Product&gt;)或IQueryables?还有Product PK 属性的名称(例如Id?)和类型(例如int?)
  • @bazz,是的,视图正在获取分组元素列表。
  • @IvanStoev 是的,变量在内存中,Product的PK类型是字符串。名字是Id
  • 只要你在内存中合并这两个列表,你就不能进行分页。您需要通过在数据库级别完成并集和组。然后,您可以相应地限制该结果集以翻阅它。没有足够的关于您的实体的信息来告诉您如何构建查询,甚至确定它是否可能。但是,无论如何,为此创建一个存储过程可能会更好,这样就不需要通过您的实体公开任何特定的 API。

标签: c# asp.net-mvc entity-framework linq pagination


【解决方案1】:

您可以对您的组进行一些重新排序吗?如果是这样,请考虑这个想法:将您最大的组放在集合的末尾并重新计算skip 计数。这是一个例子:

var result = list.GroupBy(p => p.UniqueGroupId).ToList();

var ordered = result.OrderBy(g => g.Key != null ? 0 : 1);

if (skip < result.Count - 1)
    return ordered.Skip(skip).Take(take);

return ordered.Last().Skip(skip - result.Count - 1)
    .Take(take).GroupBy(p => p.UniqueGroupId);

【讨论】:

  • 如果我使用这个返回的元素将不再被分组,.SelectMany() 正在返回一个 IEnumerable,我想维护分组的元素
  • @Oper 请查看我的更新答案。现在返回IEnumerable&lt;IGrouping&lt;string, Product&gt;&gt;
【解决方案2】:

有点挑战性,但可能。

您需要 (1) 按 复合键 进行分组,这样非空 UniqueGroupId 生成正常分组,而空 UniqueGroupId 为每个元素生成单个元素分组,然后 (2) 对分组进行排序,(3) 应用分页,(4) 展平结果并 (5) 再次分组 UniqueGroupId

var result = ProductList1.Except(productlist3).Union(ProductList2)
    .GroupBy(e => new { K1 = e.UniqueGroupId, K2 = e.UniqueGroupId == null ? e.Id : null }) // (1)
    .OrderBy(g => g.Key.K1).ThenBy(g => g.Key.K2) // (2)
    .Skip(...).Take(...) // 3
    .SelectMany(g => g) // 4
    .GroupBy(e => e.UniqueGroupId); // 5

【讨论】:

  • 嗨 ivan,我尝试了您的解决方案,它似乎有效!但是,我怎样才能用这种方法检索总页数?
  • 您可以将Skip之前的部分存储在变量中,例如var query = ...;。然后你可以使用var pageCount = query.Count(); var result = query.Skip(...)....;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
  • 2013-04-08
  • 2013-04-08
  • 2020-04-12
  • 1970-01-01
相关资源
最近更新 更多