在这个简单的例子中:
public class Person
{
public int Id {get;set;}
public int Name {get;set;}
}
什么选项性能更好:
1) 利用 NHibernate 一级缓存在第一时间和之后获取所有元素,例如:
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;
}
第二个选项是最合适的。
当您(用户)可能甚至没有“使用”所有这些实例时,一次性检索所有实例是没有用的。
如果“Person”类是一个具有大量关联的“重”类,那么创建一个“PersonView”类会更好,它只包含您想要在网格中显示的属性。
您不必映射该
PersonView
类,您只需“导入”它,以便 NHibernate 知道它的存在。
然后,您在 Person
类上创建一个查询,并定义必须使用 AliasToBean Transformer
将 Person
实例转换为 PersonView 实例。
通过这样做,NHibernate 将能够生成一个查询,该查询仅从数据库中检索必要的列,并用它填充
PersonView
实例。
与许多数据检索性能问题一样,哪个更好将取决于使用场景。
如果用户可能会在数据变得过时而无用之前仔细阅读大部分或全部页面,则选项 1 更好。在总结果集相对较小(2-3页)以及结果集不会发生太大变化(即从数据库中提取用户权限)的情况下,它也更好,允许您将整个数据集长时间存储在内存中-term,通过消除网络往返来提高未来运行的性能。
选项 2 更适合涉及长数据页和/或总结果集、“宽”记录或经常更改的数据以至于本地缓存效果不佳的情况。它将检索记录的成本分散到结果集的使用中,以达到显示记录所需的程度。这种分页结果的“延迟加载”确实会增加获取记录的总时间和开销(因为有更多的往返次数),但您的用户更有可能注意到并抱怨其搜索结果的十秒周转时间每页不到半秒。