NHibernate: sometimes I want one item, at another time I want all of them

I have a database schema that stores one “page” with many “revisions”. Like a simple wiki.

90% of the time when I load the page, I'm just interested in the latest revision. However, sometimes I need all the changes.

With NHibernate, I can map the page to versions and tell it lazy loading. However, when I access the latest version, it will load all other changes - a big waste of I / O.

My page class currently looks like:

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

How would I simulate this so that LastRevision loads automatically when the page loads, but other versions were lazy loaded if, for example, I tried to repeat them?

, LINQ to NHibernate, ICriteria ( SQL, ) .

+3
5

:

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
0

.

, . LatestRevision " " , , . (, ) .

, The LatestRevision .

Ayende, , , .

0

( ). :

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

For more information about this approach, search for "nhibernate derived properties".

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

0
source

Add the LatestRevision column (save it) and map to it. This will save you a lot of headaches.

0
source

What is the problem of having the LastRevision property and the corresponding column in the table table?

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

Source: https://habr.com/ru/post/1717440/


All Articles