使用Skip()
和Take()
扩展可以轻松完成使用LINQ的分页。
我一直在摸不着头脑,试图找到一种很好的方法来执行动态实体集合的分页 - 即可以在两个连续查询之间切换的集合。
假设没有分页的query
将返回20个MyEntity
类型的对象
以下两行将触发两个数据库匹配,这些命中将使用数据集中的所有对象填充results1
和results2
。
List<MyEntity> results1 = query.Take(10).ToList();
List<MyEntity> results2 = query.Skip(10).Take(10).ToList();
现在让我们假设数据是动态的,并且在两个查询之间将新的MyEntity
插入到数据库中,这样原始查询就会将新实体放在第一个< / strong> page。
在这种情况下,results2
列表将包含results1
中存在的实体,
导致重复的结果被发送给查询的消费者。
假设第一页中的记录已删除,则会导致错过最初应显示在results2
上的记录。
我考虑过在查询中添加一个Where()
子句来验证在前一页上没有检索到的记录,但这似乎是错误的方法,并且对第二种方案没有帮助
我考虑过保留查询执行时间戳的记录,将LastUpdatedTimestamp
附加到每个实体并过滤在上一页请求之后更改的实体。那个方向将在之后的第三页失败......
这通常是怎么做的?
有没有办法针对数据库的旧快照运行查询?
修改 后台是一个Asp.NET MVC WebApi服务,它响应一个简单的GET请求来检索实体列表。客户端检索实体页面,并将其呈现给用户。向下滚动时,客户端向服务发送另一个请求,以检索另一个实体页面,这些实体应该添加到已经呈现给用户的第一页。
答案 0 :(得分:0)
解决此问题的一种方法是保留第一个查询的TimeStamp并排除在该时间之后添加的任何结果。然而,这个解决方案将数据置于“陈旧”状态,即数据在某个时间点固定,这通常是个坏主意,除非你有充分的理由去做。
另一种方法(再次取决于你的应用程序)是将所有对象的列表存储在内存中,然后一次只显示一定数量的结果。
List<Entity> _list;
public class SomeCtor()
{
_list = _db.Entities.ToList();
}
public List<Entity> GetFirst10
{
get
{
return _list.Take(10);
}
}
public List<Entity> GetSecond10
{
get
{
return _list.Skip(10).Take(10);
}
}