NHibernate在许多查询中有很多对很多结果

时间:2013-08-27 12:11:41

标签: c# nhibernate

我正在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个书签):

Example with NHibernate Profiler (3 bookmarks)

1 个答案:

答案 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/>