1

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 IList<TagWithBookmarkCount> GetTagsWithBookmarkCount(string username)
{
    ICriteria criteriaQuery = SessionFactory.GetCurrentSession()
            .CreateCriteria(typeof(Tag))
            .CreateAlias("User", "u")
            .CreateAlias("Bookmarks", "b")
            .SetProjection (Projections.ProjectionList()
            .Add (Projections.GroupProperty("Title"), "Title")
            .Add (Projections.GroupProperty("Description"), "Description")
            .Add (Projections.Count("Bookmarks"), "BookmarkCount"))
            .Add(Restrictions.Eq("u.Username", username));

    criteriaQuery.SetResultTransformer(Transformers.AliasToBean (typeof(TagWithBookmarkCount)));

    IList<TagWithBookmarkCount> tags = criteriaQuery.List<TagWithBookmarkCount>();

    return tags;
}

これにより、次のクエリが生成されます。

SELECT this_.Title       as y0_,
   this_.Description as y1_,
   count(this_.Id)   as y2_
FROM   Tags this_
   inner join TagsBookmarks bookmarks4_
     on this_.Id = bookmarks4_.TagId
   inner join Bookmarks b2_
     on bookmarks4_.BookmarkId = b2_.Id
   inner join Users u1_
     on this_.UserId = u1_.Id
WHERE  u1_.Username = 'Mr.nuub' /* @p0 */
GROUP  BY this_.Title,
      this_.Description

ブックマークの内部結合は必要ありません。ブックマークとタグの両方で、HasManyToMany で Fluent マッピングを使用します。ジャンクション テーブルのマッピングはベスト プラクティスではないと思います。ジャンクション テーブルをマッピングせずにこの結合を回避できますか? それとも気にしなくていいのでしょうか?

4

1 に答える 1