代码之家  ›  专栏  ›  技术社区  ›  Paul Stovell

NHibernate:有时我只想要一件,有时我想要全部

  •  3
  • Paul Stovell  · 技术社区  · 16 年前

    public class Page
    {
        public Page()
        {
            Revisions = new HashedSet<Revision>();
        }
    
        public virtual ISet<Revision> Revisions { get; private set; }
    
        public virtual Revision LatestRevision
        {
            get { return Revisions.OrderByDescending(x => x.Revised).FirstOrDefault(); }
        }
    
        public virtual Revision Revise()
        {
            var revision = new Revision();
            // ...
            revision.Entry = this;
            revision.Revised = DateTime.UtcNow;
            Revisions.Add(revision);
            return revision;
        }
    }
    

    我该如何建模,以便在加载页面时自动加载LatestRevision,但如果我试图迭代其他修订,则延迟加载其他修订?

    我特别希望有一个与LINQ to NHibernate兼容的解决方案,但使用ICriteria(如果需要的话,甚至是SQL)就足够了。

    5 回复  |  直到 16 年前
        1
  •  0
  •   Darren    16 年前

    我也在处理类似的问题。

    按照你在那里的样子进行精确的地图绘制怎么样。LatestRevision属性可以映射为与修订表的一对一映射,修订将与您已有的一致。您必须有一个setter(可能将其设置为私有)并在修订方法中管理关系。

    我还看到了一个帖子 Ayende 它使用属性的formula属性,我从未使用过它,但看起来它可能符合要求。

        2
  •  0
  •   Christopher Bennage    16 年前

    您可以在映射文件中使用派生属性(而不是在属性中执行逻辑)。它可能看起来像这样:

    <property name="LatestRevision"
              forumla="select top r.f1, r.f2, r.etc from Revisions order by revised desc"
              type="Revision" />
    

    有关此方法的更多信息,请搜索“nhibernate衍生属性”。

    https://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html_single/

        3
  •  0
  •   Fredy Treboux    16 年前

    添加LatestRevision列(维护它)并映射到该列。 这会为你省去很多麻烦。

        4
  •  0
  •   Community Mohan Dere    9 年前

    我最终选择了以下解决方案:

    Partially Populate Child Collection with NHibernate

    我的页面现在有以下属性:

    public virtual Revision CurrentRevision 
    { 
        get
        {
            return _revision ?? Revisions.OrderByDescending(x => x.Revised).FirstOrDefault();
        }
        set { _revision = value; }
    }
    
    public virtual ISet<Revision> Revisions { get; private set; }
    

    加载代码为:

    public Page GetPage(string name)
    {
        var entryHash = (Hashtable)_session.CreateCriteria<Page>("page")
            .Add(Restrictions.Eq("page.Name", name))
            .CreateCriteria("Revisions", "rev")
                .AddOrder(Order.Desc("rev.Revised"))
            .SetMaxResults(1)
            .SetResultTransformer(Transformers.AliasToEntityMap)
            .UniqueResult();
        var page = (Page)entryHash["page"];
        page.LatestRevision = (Revision)entryHash["rev"];
        return page;
    }
    

    NHProf将此显示为现在正在执行的唯一查询,这是完美的:

    SELECT   top 1 this_.Id            as Id3_1_,
                   this_.Name          as Name3_1_,
                   this_.Title         as Title3_1_,
                   rev1_.Id            as Id0_0_,
                   rev1_.Body          as Body0_0_,
                   rev1_.Revised       as Revised0_0_,
                   ....
    FROM     [Page] this_
             inner join [Revision] rev1_
               on this_.Id = rev1_.PageId
    WHERE    this_.Name = 'foo' /* @p0 */
    ORDER BY rev1_.Revised desc
    
        5
  •  0
  •   dariol    16 年前

    public class Page
    {
        public Page()
        {
            Revisions = new HashedSet<Revision>();
        }
    
        public virtual ISet<Revision> Revisions { get; private set; } // lazy="true"
    
        public virtual Revision LatestRevision { get; private set; } // lazy="false"
    
        public virtual Revision Revise()
        {
            var revision = new Revision();
            // ...
            revision.Entry = this;
            revision.Revised = DateTime.UtcNow;
            Revisions.Add(revision);
            LatestRevision = revision; // <- there you have latest revision
            return revision;
        }
    }