考虑两个实体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"));
其中page
和pageSize
是计算位。
问题是因为最大结果和第一个结果是在数据库中计算的,而不同的根在外面完成,行数不匹配。
有没有办法解决这个问题?
答案 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语句,所有数据都将被有效加载。参见: