我正在ASP.NET MVC中开发书签系统,我使用NHibernate来查询数据库。
我有很多关系:
型号:
public class Bookmark
{
public virtual string Title { get; set; }
public virtual string Link { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public virtual string Title { get; set; }
public virtual string Description { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Bookmark> Bookmarks { get; set; }
}
我希望获得一个标记,通过其书签循环,并通过其标记为每个书签循环。为此,我使用了这个:
public Tag GetTagByTitle(string username, string title)
{
ICriteria criteriaQuery = SessionFactory.GetCurrentSession()
.CreateCriteria(typeof(Tag))
.SetFetchMode("Bookmarks", FetchMode.Eager)
.CreateAlias("User", "User")
.Add(Restrictions.Eq("Title", title))
.Add(Restrictions.Eq("User.Username", username));
IList<Tag> tags = criteriaQuery.List<Tag>();
Tag tag = tags.FirstOrDefault();
return tag;
}
这给了我带有书签的标签。但是对于每个书签,它会自动执行另一个查询以获取其标记(延迟加载?)。所以,如果我有10个书签,我会获得1 + 10个查询。是否可以通过一个或两个查询来执行此操作?
NHibernate Profiler示例(3个书签):
答案 0 :(得分:1)
您可以使用CreateAlias
热切地提取书签,还可以让您深入挖掘另一个图层,以指定您希望如何获取标记。
ICriteria criteriaQuery = SessionFactory.GetCurrentSession()
.CreateCriteria(typeof(Tag))
.CreateAlias("Bookmarks", "b", JoinType.LeftOuterJoin)
.CreateAlias("b.Tags", "bt", JoinType.LeftOuterJoin)
.CreateAlias("User", "User")
.Add(Restrictions.Eq("Title", title))
.Add(Restrictions.Eq("User.Username", username))
.SetResultTransformer(Transformers.DistinctRootEntity);
编辑:修正了查询。很抱歉。显然SetFetchMode
仅适用于直接位于查询的根实体之外的关系。用CreateAlias
替换它可以解决问题。
将所有这些左外连接添加到集合中,您需要稍微修改实体并更新映射以防止重复的连接显示在集合中。而不是ICollection<T>
,而是使用ISet<T>
命名空间中的Iesi.Collections.Generic
,并将您的映射更改为使用<set/>
而不是<bag/>
。