通过集合获取Paginated实体

考虑两个实体具有one-to-many收集Vehicles

 public class Person { public IList Vehicles { get; set;} } public class Vehicle { public string Name { get; set;} public Person Owner { get; set; } } 

我显示一个有车辆的人员网格,并显示网格中第一辆车的名称。 网格是分页的。 我使用以下标准来获取数据

我有一个加载网格视图数据的标准

 var criteria = DetachedCriteria.For() .CreateAlias("Vehicles","vehicle", JoinType.InnerJoin) .SetResultTransformer(new DistinctRootEntityResultTransformer()) .SetMaxResults(pageSize) .SetFirstResult((page - 1) * pageSize) criteria.Add(Restrictions.Eq("vehicle.Name", "super")); 

其中pagepageSize是计算位。

问题是因为最大结果和第一个结果是在数据库中计算的,并且不同的根在外部完成,行数不匹配。

有没有办法解决这个问题?

这种查询应始终使用subquery而不是任何类型的JOIN 。 这也意味着,colleciton项目引用了父项(如我们的情况)

所以,在这里我们为Vehicle创建内部选择:

 var vehicles = DetachedCriteria.For(); // add any amount or kind of WHERE parts vehicles.Add(Restrictions.Eq("vehicle.Name", "super")) // and essential SELECT Person ID vehicles.SetProjection( Projections.Property("Owner.ID")); 

现在,我们可以调整上面的查询,只在root / parent级别上工作:

 var criteria = DetachedCriteria.For() // instead of this // .CreateAlias("Vehicles","vehicle", JoinType.InnerJoin) // we will use subquery .Add(Subqueries.PropertyIn("ID", vehicles)); // Wrong to use this approach at all //.SetResultTransformer(new DistinctRootEntityResultTransformer()) .SetMaxResults(pageSize) .SetFirstResult((page - 1) * pageSize) 

那会像这样创建SELECT:

 SELECT p.... FROM Person AS p WHERE p.ID IN ( SELECT v.OwnerId FROM Vehcile AS v WHERE v.Name = 'super' ... ) 

也可以看看:

  • 查询HasMany引用
  • 在NHibernate中,使用Disjunction可以得到双重结果

以及如何获取Vehicles的集合(直到现在只用于过滤) ? 最好的(如果不是唯一的)方法是使用1 + 1 SELECT语句。 简单的内置解决方案是batch-size设置。 只需使用此设置标记Vehicles集合(例如batch-size="25" ),并使用更多SELECT语句,所有数据都将被有效加载。 看到:

  • 19.1.5。 使用批量提取
  • 如何在NHibernate中没有重复地加载加载关联?