【问题标题】:How to get row index by entity key in a dynamically built query using Entity Framework如何使用实体框架在动态构建的查询中按实体键获取行索引
【发布时间】:2012-03-22 14:44:56
【问题描述】:

在网格中,我需要按 ID 分页到记录。这就是为什么我需要在用户过滤和用户排序的集合中找到它的索引。

我正在与LINQ to Entities 合作。查询是根据用户输入动态构建的。

该表包含太多(超过 10^5)条记录,以下 Stack Overflow suggestion 无济于事:

Recs = Recs.Where( /* Filters */ );
Recs = Recs.OrderBy( /* Sort criteria */ );
Recs.AsEnumerable()
        .Select((x,index) => new {RowNumber = index, Record = x})
        .Where(x=>x.Record.ID = 35);

由于 LINQ to Entities 不支持 Select((entity, index) => ...),因此我需要从 SQL 服务器下载 250,000 条记录,这样我才能决定显示第 25,000 页。

目前,我最有希望的想法是将每个排序标准转换为过滤器。因此,查找按身高升序排序的人的索引将变成计算较短的人(排序标准“身高升序”=>过滤“身高小于”+计数)。

我应该如何处理这个问题?这个问题已经解决了吗? .NET 是否有任何图书馆可以让我走到一半?

【问题讨论】:

  • 我不太明白你在问什么,你是在问如何在特定页面上找到特定选择的键值?或者您是否想找出一次检索单个页面的最佳方法?
  • 给定一个行 ID/实体键,我想在排序和过滤的查询中找到该特定行的位置。假设用户决定按姓名对人员进行排序,人员集为 [{id: 11, name:"Amy"}, {id: 1, name"Joe"}, {id: 2, name"Zack"}],给定 id 11 我需要得到 index=1, id = 1 => index = 2, id = 2 => index = 3
  • 好的,所以你有了数据库Id,你需要在UI中找到对应的行,对吧?什么是 UI、ASP.NET、WinForms、WPF?
  • 这是 ASP MVC 的 Telerik 扩展,但我认为将所有数据移动到 UI 中需要很长时间,然后尝试找到索引。我说的是数百万条记录。
  • 你自己的建议有什么问题? recs.OrderBy(r => r.someProperty).Count(r => r.index < someIndex)?

标签: c# .net sql-server entity-framework linq-to-entities


【解决方案1】:

这是一个递归函数,您可以调用它来计算行号。如果您的数据库记录经常更改,它可能不起作用,因为这会多次调用数据库,每次都会将搜索范围缩小一半。

public static int FindRowNumber<T>(IQueryable<T> query, Expression<Func<T, bool>> search, int skip, int take)
{
  if(take < 1) return -1;
  if(take == 1) return query.Skip(skip).Take(take).Any(search) ? skip : -1;      


  int bottomSkip = skip;
  int bottomTake = take / 2;
  int topSkip = bottomTake + bottomSkip;
  int topTake = take - bottomTake;

  if(query.Skip(bottomSkip).Take(bottomTake).Any(search))
  {        
    return FindRowNumber(query, search, bottomSkip, bottomTake);
  }
  if(query.Skip(topSkip).Take(topTake).Any(search))
  {
    return FindRowNumber(query, search, topSkip, topTake);
  }

  return -1;
}

你这样称呼它:

var query = ... //your query with ordering and filtering
int rownumber = FindRowNumber(query, x => x.Record.ID == 35, 0, query.Count());

【讨论】:

  • 这是一种有趣的方法,但不如我在问题中建议的方法快,我最终通过(ab)使用网格过滤系统来实现。另一方面,它明显优于我的 sn-p 中的方法。感谢您的努力!
  • @CălinDarie - 你应该发布你的答案并接受它。我认为人们会从中受益。
猜你喜欢
  • 2011-08-18
  • 2011-07-29
  • 1970-01-01
  • 1970-01-01
  • 2015-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多