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 マッピングを使用します。ジャンクション テーブルのマッピングはベスト プラクティスではないと思います。ジャンクション テーブルをマッピングせずにこの結合を回避できますか? それとも気にしなくていいのでしょうか?