代码之家  ›  专栏  ›  技术社区  ›  Derek Greer

如何为NHibernate中的关联指定排序标准?

  •  2
  • Derek Greer  · 技术社区  · 14 年前

    为实体 ParentEntity 类型的集合 ChildEntity 其中包含 Order int类型的属性,如何使用按排序的子集合来检索父实体 订单 特别是通过使用标准 如NHibernate文件第12.4节所述的API here ?

    我尝试使用类似以下代码:

    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 声明。第一个选择包含 order by 它对检索到的关联列进行排序,但第二列不排序,而这似乎是从中填充集合的列。

    注意,我已经尝试将nhibernate配置为执行外部连接获取,如果没有外部连接获取,则在没有标准的情况下工作正常。也就是说,它生成两个未配置外部联接的查询,但只生成一个配置了外部联接的查询。不管怎样,添加的条件似乎会导致额外的查询。

    请将答案限制在如何使用标准API来完成这项工作,或解释为什么这项工作不起作用。我知道排序可以通过映射来完成,但是我试图理解使用标准方法的具体问题是什么。

    ===编辑======

    以下是模型和映射:

    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();
        }
    }
    

    ====编辑2====

    作为更新,在将not.lazyload()添加到父级之后,只有一个 选择 但是,结果仍然是未排序的。

    3 回复  |  直到 14 年前
        1
  •  1
  •   Derek Greer    14 年前

    从我观察到的行为来看,问题似乎是,虽然可以对关联施加约束(如 docs )这样的约束只与它们作为根实体有意义的过滤器的程度相关。请考虑文档中的以下示例:

    IList cats = sess.CreateCriteria(typeof(Cat))
    .Add( Expression.Like("Name", "F%")
    .CreateCriteria("Kittens")
        .Add( Expression.Like("Name", "F%") )
    .List();
    

    这句话是说把名字以“f”开头的所有猫都还给我,但只有那些名字以“f”开头的猫。 这并不是说归还名字以“f”开头的小猫。 .订购的工作方式类似。我们可能会要求按名称订购小猫,NHibernate很乐意将其作为标准的一部分进行传递,但是这样的订购与小猫如何被退回没有关系。因此,我的结论是,使用标准API不能用于筛选或排序返回的关联。

    文档的上述部分确实说明了返回的关联不是由标准预先过滤的,但是直到我了解了关联标准的用途之后,我才完全理解它的含义。

        2
  •  0
  •   Frederik Gheysels    14 年前

    你怎么给孩子们画地图的? 如果您已将孩子映射为“有序列表”(map/list/dictionary),则只能指示nhibernate以有序方式检索孩子。

    例如: http://ayende.com/Blog/archive/2009/06/02/nhibernate-mapping-ltlistgt.aspx

    我已经将这些孩子映射为一个未排序的列表(集合/包),那么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();
        }
    
    }
    
        3
  •  0
  •   mxmissile    14 年前

    没有看到你的模型和地图有点困难。但也许是这样?

     var criteria = session.CreateCriteria<ParentEntity>();
     criteria.Add(Restrictions.Eq("Id", id))
                    .CreateAlias("Children", "children")
                    .AddOrder(Order.Desc("children.Order"));