通过集合获取Paginated实体

时间:2014-05-05 14:55:06

标签: c# nhibernate pagination nhibernate-criteria

考虑两个实体Person,其中one-to-many集合Vehicles

public class Person
{
    public IList<Vehicle> Vehicles { get; set;}
}

public class Vehicle 
{
   public string Name { get; set;}

   public Person Owner { get; set; }
}

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

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

var criteria = DetachedCriteria.For<Person>()
    .CreateAlias("Vehicles","vehicle", JoinType.InnerJoin)
    .SetResultTransformer(new DistinctRootEntityResultTransformer())
    .SetMaxResults(pageSize)
    .SetFirstResult((page - 1) * pageSize)

criteria.Add(Restrictions.Eq("vehicle.Name", "super"));

其中pagepageSize是计算位。

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

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

1 个答案:

答案 0 :(得分:3)

此类查询应始终使用subquery而不是任何类型的 JOIN 。这也意味着,colleciton项目引用了父(在我们的例子中)

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

var vehicles = DetachedCriteria.For<Vehicle>();
// 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 /父级别上工作:

var criteria = DetachedCriteria.For<Person>()

// 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' ...
)

另见:

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