如何为NHibernate中的关联指定排序条件?
对于具有类型为如何为NHibernate中的关联指定排序条件?,nhibernate,Nhibernate,对于具有类型为ChildEntity的集合的实体ParentEntity,该集合包含类型为int的Order属性,如何通过使用NHibernate文档第12.4节中讨论的标准API检索父实体和按顺序排序的子集合 我尝试过使用类似以下的代码: public ParentEntity GetById(int id) { ICriteria criteria = _sessionFactory.GetCurrentSession().CreateCriteria(typeof (ParentE
ChildEntity
的集合的实体ParentEntity
,该集合包含类型为int的Order
属性,如何通过使用NHibernate文档第12.4节中讨论的标准API检索父实体和按顺序排序的子集合
我尝试过使用类似以下的代码:
public ParentEntity GetById(int id)
{
ICriteria criteria = _sessionFactory.GetCurrentSession().CreateCriteria(typeof (ParentEntity));
criteria.Add(Restrictions.Eq("Id", id))
.CreateCriteria("Children")
.AddOrder(Order.Desc("Order"));
return (ParentEntity) criteria.List()[0];
}
不幸的是,此代码生成2条SELECT
语句。第一个select包含一个排序依据,它对检索到的关联列进行排序,但第二个select不包含排序依据,这似乎就是从中填充集合的列
注意,我已经尝试将NHibernate配置为执行外部联接获取,如果没有外部联接获取,则在没有条件的情况下可以正常工作。也就是说,它生成两个没有配置外部联接的查询,但只生成一个配置了外部联接的查询。添加的条件似乎会导致额外的查询
请限制回答如何使用criteria API完成这项工作,或者解释为什么这项工作不起作用。我知道排序可以通过映射来完成,但我试图理解使用criteria方法的具体问题
==编辑====
以下是模型和映射:
public class ParentEntity
{
public virtual int Id { get; private set; }
public virtual IList<ChildEntity> Children { get; set; }
public ParentEntity()
{
Children = new List<ChildEntity>();
}
}
public class ChildEntity
{
public virtual int Id { get; private set; }
public virtual ParentEntity Parent { get; private set; }
public virtual int Order { get; private set; }
protected ChildEntity()
{
}
public ChildEntity(int order)
{
Order = order;
}
}
public class ParentEntityMap : ClassMap<ParentEntity>
{
public ParentEntityMap()
{
WithTable("Parent");
Id(p => p.Id);
HasMany(p => p.Children)
.KeyColumnNames.Add("Parent_Id")
.Cascade.All();
}
}
public class ChildEntityMap : ClassMap<ChildEntity>
{
public ChildEntityMap()
{
WithTable("Child");
Id(c => c.Id);
Map(c => c.Order, "[Order]");
References(c => c.Parent, "Parent_Id")
.Cascade.All();
}
}
公共类父实体
{
公共虚拟整数Id{get;private set;}
公共虚拟IList子项{get;set;}
公共父实体()
{
Children=新列表();
}
}
公共类子实体
{
公共虚拟整数Id{get;private set;}
公共虚拟父实体父{get;private set;}
公共虚拟整数顺序{get;私有集;}
受保护的子实体()
{
}
公共子实体(整数顺序)
{
订单=订单;
}
}
公共类ParentityMap:ClassMap
{
公共parentitymap()
{
WithTable(“母公司”);
Id(p=>p.Id);
有很多孩子(p=>p.Children)
.KeyColumnNames.Add(“父项Id”)
.Cascade.All();
}
}
公共类ChildEntityMap:ClassMap
{
公共儿童地图()
{
WithTable(“儿童”);
Id(c=>c.Id);
映射(c=>c.顺序,“[顺序]”);
参考资料(c=>c.父项,“父项Id”)
.Cascade.All();
}
}
==编辑2====
作为更新,在将Not.LazyLoad()添加到父级后,仅生成一个
SELECT
,但是,结果仍然未排序。如何映射子级?
如果已将子项映射为“有序列表”(map/list/dictionary),则只能指示NHibernate应以有序方式检索子项
例如:
如果您已将这些子项映射为未排序的列表(集合/包),那么NHibernate将无法为您排序这些子项。在这种情况下,当用户访问这些子对象时,您必须对它们进行排序
public class Parent
{
private ISet<Child> _children = new HashedSet<Child>();
public ReadOnlyCollection<Child> Children
{
new List<Child>(_children).OrderBy(child => child.SequenceNr).ToList().AsReadOnly();
}
}
公共类父类
{
私有ISet_children=new HashedSet();
公共只读集合子项
{
新列表(_children).OrderBy(child=>child.SequenceNr.ToList().AsReadOnly();
}
}
如果看不到您的模型和映射,会有点困难。但也许是这样的
var criteria = session.CreateCriteria<ParentEntity>();
criteria.Add(Restrictions.Eq("Id", id))
.CreateAlias("Children", "children")
.AddOrder(Order.Desc("children.Order"));
var-criteria=session.CreateCriteria();
标准。添加(限制。等式(“Id”,Id))
.CreateAlias(“儿童”、“儿童”)
.AddOrder(Order.Desc(“children.Order”);
从我观察到的行为来看,问题似乎是,虽然可以对关联设置约束(如第12.4节所示),但此类约束仅在其作为根实体的有意义过滤器的程度上相关。从DOCS中考虑下面的例子:
IList cats = sess.CreateCriteria(typeof(Cat))
.Add( Expression.Like("Name", "F%")
.CreateCriteria("Kittens")
.Add( Expression.Like("Name", "F%") )
.List();
这意味着把所有名字以“F”开头的猫都还给我,但只给那些有名字以“F”开头的小猫的猫这并不是说返回名称以“F”开头的小猫。。订购的工作方式与此类似。我们可能会要求按名称订购小猫,NHibernate很乐意将其作为标准的一部分,但这种订购方式不会影响小猫的退货方式。因此,我的结论是,不能使用CriteriaAPI来过滤或排序返回的关联
上述文档部分确实指出,返回的关联未按标准进行预筛选,但在我理解关联标准的用途之前,我并不完全理解其含义。我使用的是fluent,将集合声明为IList,并尝试将其映射为默认包和列表(例如,HasMany(x=>x.Children).AsList()),但两者都显示相同的结果。此外,生成的第一个SELECT对结果进行了正确排序,因此,如果没有生成第二个SELECT,则列表将按需要填充。我也尝试使用别名,但没有任何区别。