0

Skip()使用和Take()扩展可以轻松地使用 LINQ 进行分页。
很长一段时间以来,我一直在摸索,试图找到一种对实体的动态集合执行分页的好方法——即可以在两个顺序查询之间更改的集合。

假设query没有分页将返回 20 个类型的对象MyEntity
以下两行将触发两个数据库命中,这些命中将填充数据集中results1results2所有对象。

List<MyEntity> results1 = query.Take(10).ToList();
List<MyEntity> results2 = query.Skip(10).Take(10).ToList();

现在让我们假设数据是动态的,并且MyEntity在两个查询之间将一个新实体插入到数据库中,这样原始查询会将新实体放在第一页中。
在这种情况下,results2list 将包含一个也存在于 中的实体results1
从而导致发送给查询消费者的结果重复。

假设从第一页删除了一条记录,这将导致丢失一条原本应该出现的记录results2

我考虑Where()在查询中添加一个子句,以验证在前一页上未检索到的记录,但这似乎是错误的方法,并且对第二种情况没有帮助。

我考虑记录查询执行的时间戳,将 a 附加LastUpdatedTimestamp到每个实体并过滤在上一页请求之后更改的实体。之后,该方向将在第三页失败......

这通常是如何完成的?
有没有办法对数据库的旧快照运行查询?

编辑: 背景是一个 Asp.NET MVC WebApi 服务,它响应一个简单的 GET 请求来检索实体列表。客户端检索实体页面,并将它们呈现给用户。向下滚动时,客户端向服务发送另一个请求,以检索另一个实体页面,该实体应添加到已经呈现给用户的第一页。

4

1 回答 1

0

解决此问题的一种方法是保留第一个查询的时间戳并排除在该时间之后添加的任何结果。然而,此解决方案将数据置于“陈旧”状态,即数据固定在某个时间点,这通常是一个坏主意,除非您有充分的理由这样做。

另一种方法(同样取决于您的应用程序)是将所有对象的列表存储在内存中,然后一次只显示一定数量的结果。

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);
    }
}
于 2013-08-28T17:52:15.670 回答