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

有时我想要一件,有时我想要全部

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

    我有一个数据库模式,它存储一个“页面”和许多“修订”。就像一个简单的wiki。

    90%的时候,当我加载一个页面时,我只是对最新版本感兴趣。但是,有时我需要所有的修改。

    使用nhibernate,我可以将页面映射到修订版,并告诉它懒惰加载。但是,当我访问最新版本时,它将加载所有其他版本——这是对I/O的极大浪费。

    我的页面类当前类似于:

    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属性可以作为一对一的映射映射到Revisions表,并且这些修订将和您已经得到的一样。您必须有一个setter(可能使其成为私有的)并在review方法中管理关系。

    一个问题是,最新的版本仍然在修订版中。

    我也遇到过一个帖子 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    8 年前

    最后我提出了解决方案:

    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 年前

    页表中的lateStrevision属性和相应列有什么问题?

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