对于具有类型ParentEntity
的集合的实体ChildEntity
,其中包含类型为int的Order
属性,如何使用按{{1}排序的子集合检索父实体} 特别是通过使用NHibernate docs here第12.4节中讨论的Criteria API?
我尝试使用类似以下的代码:
Order
不幸的是,这段代码产生了2个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];
}
语句。第一个选择包含SELECT
,它对检索到的关联列进行排序,但第二个选择不排序,这似乎是从中填充集合的列。
注意,我已经尝试过配置NHibernate来进行外部联接提取,但没有标准就可以按预期工作。也就是说,它会在没有配置外部联接的情况下生成两个查询,但只有一个查询配置了外部联接。添加标准似乎无论如何都会引起额外的查询。
请使用条件API或解释为什么这不起作用限制答案。我知道可以通过映射完成排序,但我正在尝试使用条件方法了解具体问题。
以下是模型和映射:
order by
作为更新,将Not.LazyLoad()添加到Parent后,只生成一个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();
}
}
,但结果仍未排序。
答案 0 :(得分:1)
从我观察到的行为来看,问题似乎是虽然约束可以放在关联上(如docs的第12.4节所示),但这种约束只与它们充当根实体的有意义的过滤器。请考虑以下文档中的示例:
IList cats = sess.CreateCriteria(typeof(Cat))
.Add( Expression.Like("Name", "F%")
.CreateCriteria("Kittens")
.Add( Expression.Like("Name", "F%") )
.List();
这就是说给我回到名字以“F”开头的所有猫,但只有那些猫的名字以“F”开头的猫。 这并不是说返回名称以“F”开头的小猫。订购以类似的方式工作。我们可能已经要求小猫按名称订购,NHibernate很乐意将其作为标准的一部分传递,但这样的排序与小猫的返回方式无关。因此,我的结论是使用Criteria API不能用于过滤或排序返回的关联。
文档的前面部分确实说明了返回的关联没有按标准进行预过滤,但在我理解了关联标准的用途之前,我并不完全明白其含义。
答案 1 :(得分:0)
你是如何映射孩子的? 如果您已将它们映射为“有序列表”(地图/列表/字典),则只能指示NHibernate应以有序方式检索子项。
例如: http://ayende.com/Blog/archive/2009/06/02/nhibernate-mapping-ltlistgt.aspx
我已将孩子们映射为无序列表(set / bag),然后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();
}
}
答案 2 :(得分:0)
有点难以看到你的模型和地图。但也许是这样的?
var criteria = session.CreateCriteria<ParentEntity>();
criteria.Add(Restrictions.Eq("Id", id))
.CreateAlias("Children", "children")
.AddOrder(Order.Desc("children.Order"));