NHibernate分页性能(更好的选择)

时间:2010-11-09 18:56:39

标签: c# nhibernate paging

在那个简单的案例中:

public class Person
{
     public int Id {get;set;}
     public int Name {get;set;}
}
  • 我需要生成一个带分页和排序的网格
  • 我的数据库有大约10万人

哪种选择有更好的表现:

1)第一次获取所有元素并在利用NHibernate First Level Cache之后,例如:

personRep.FindAll().OrderBy(s =>s.Name).AsPagination(pageNumber,pageSize);

Obs。:AsPagination是一种扩展方法......

2)仅从数据库中获取实际页面,例如:

   public virtual IList<T> GetPaginedList(int __pageIndex, int __pageSize,out int __total)
    {            
        var _rowCount = Session.CreateCriteria(typeof(T))
            .SetProjection(Projections.RowCount()).FutureValue<Int32>();

        var _results = Session.CreateCriteria(typeof(T))
            .SetFirstResult(__pageIndex * __pageSize)
            .SetMaxResults(__pageSize)
            .Future<T>();

        __total = _rowCount.Value; 
        return _results;
    } 

2 个答案:

答案 0 :(得分:4)

第二种选择是最合适的。

当你(用户)甚至没有“使用”所有这些实例时,一次性检索所有实例是没用的。

如果'Person'类是一个有很多关联的'重'类,那么创建一个'PersonView'类会更好,它只包含你想要在Grid中显示的属性。

您不必映射PersonView类,您只需要'导入'它,以便NHibernate知道它的存在。 然后,在Person类上创建一个查询,并定义必须使用AliasToBean TransformerPerson实例转换为PersonView实例。

通过这样做,NHibernate将能够生成一个只从DB中检索必要列的查询,并用它填充PersonView个实例。

答案 1 :(得分:1)

与许多数据检索性能问题一样,哪些更好将取决于使用场景。

如果用户可能会在数据过于陈旧无法使用之前仔细阅读大部分或全部页面,则选项1会更好。在总结果集相对较小(2-3页)的情况下,以及结果集不会发生太大变化(即从数据库中提取用户权限)的情况下,它也会更好,允许您将整个数据集存储在内存中 - 通过消除网络往返来提高未来运行的性能。

选项2更适用于涉及长数据页和/或总结果集,“宽”记录的情况,或者经常更改的数据,以便本地缓存不会带来太多好处。它将在结果集使用过程中检索记录的成本分摊到显示它们所需的程度。分页结果的这种“延迟加载”确实增加了获取记录的总时间和开销(因为有更多的往返),但是您的用户更有可能注意到并抱怨他们的搜索结果有10秒的周转时间每页超过半秒。