我有一个数据库模式,存储一个带有许多“修订版”的“页面”。就像一个简单的维基。
我加载页面时有90%的时间,我只对最新版本感兴趣。但是,有时候我想要所有的修改。
使用NHibernate,我可以将Page映射到Revisions,并告诉它延迟加载。但是,当我访问最新版本时,它将加载所有其他修订 - 大大浪费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)也足够了。
答案 0 :(得分:0)
我也在处理类似的问题。
如何完全按照您的方式进行映射。 LatestRevision属性可以映射为修订表的一对一映射,修改将是您已经获得的。您必须拥有一个setter(可能使其成为私有)并在修订方法中管理关系。
一个问题是LatestRevision仍将处于修订集中。
我还看到了Ayende的帖子,该帖子使用了属性的公式属性,我从来没有使用它,但看起来它可能符合要求。
答案 1 :(得分:0)
您可以在映射文件中使用派生属性(而不是在属性中执行逻辑)。它可能看起来像这样:
<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/
答案 2 :(得分:0)
添加LatestRevision列(维护它)并映射到该列。 它会为你节省很多麻烦。
答案 3 :(得分:0)
我最终选择了解决方案:
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
答案 4 :(得分:0)
在Page表中有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;
}
}