在 NHibernate 中,即使是最简单的连接也会变得复杂
Even easiest join gets complicated in NHibernate
好的,所以我有以下数据库模式
并且是一对多的关系(一个相册可以有很多张图片)
映射看起来像这样:
<property name="NumID"...>
<.../>
</property>
<set name="Images" inverse="true" cascade="delete" generic="true">
<key>
<column name="AlbumID" />
</key>
<one-to-many class="Images" />
</set>
并且默认抓取设置为惰性
现在问题来了:
我想加载包含图片的相册(我知道 NumID)
我会使用以下 SQL:
select * from Images img
join Albums alb
on alb.NumId = img.AlbumId
where img.NumID = 1026
但是在 NHibernate 中我该怎么做呢?当然,我尝试了很多不同的方法,取得了不同程度的成功,但没有什么比 SQL 本身更简单了。
作为一个加重因素,我确实需要整个对象(专辑)(或者至少我需要 NumID 和 Name, 不是懒加载)
我试过这个:
/* 1 */
var tmp1 = session.QueryOver<Images>()
.Where(i => i.NumID == ImageID) //The ImageID is for example 1026
.JoinQueryOver(i => i.Album)
.Select(x => x.Album)
.List<Album>();
// Decent to read, but this only loads the NumID from the album
/* 2 */
var tmp2 = session.Query<Images>()
.Join(DBContext.GetQuery<Albums>(), i => i.Albums.NumID, a => a.NumID,
(imgAlias, albAlias) => new {imgAlias, albAlias})
.Where(x => x.imgAlias.NumID == ImageID) //ImageID = 1026
.Select(x => x.albAlias).ToList();
// This one actually works, but it's almost totally unreadable!
应该怎么做?
方式(我主要使用,如果不是唯一的话) - 是使用子查询 (内部SELECT)
// subquery returning the ALBUM ID
var sq = QueryOver.Of<Image>()
.Where(i => i.NumID == ImageID) //The ImageID is for example 1026
.Select(i => i.Album.Id); // here we return the Album.ID (column AlbumID)
// just Albums with searched Image
var query = QueryOver.Of<Album>()
.WithSubquery
.WhereProperty(a => a.Id)
.In(sq)
...
.List<Album>();
最大的优势是,Album
结果 (SELECT) 是 flat (not joined with multi Images)
- 因此我们可以轻松使用分页:
...
.Take(50)
.Skip(50)
.List<Album>();
检查其他一些子查询QueryOver: select columns from subquery
好的,所以我有以下数据库模式
并且是一对多的关系(一个相册可以有很多张图片)
映射看起来像这样:
<property name="NumID"...>
<.../>
</property>
<set name="Images" inverse="true" cascade="delete" generic="true">
<key>
<column name="AlbumID" />
</key>
<one-to-many class="Images" />
</set>
并且默认抓取设置为惰性
现在问题来了: 我想加载包含图片的相册(我知道 NumID)
我会使用以下 SQL:
select * from Images img
join Albums alb
on alb.NumId = img.AlbumId
where img.NumID = 1026
但是在 NHibernate 中我该怎么做呢?当然,我尝试了很多不同的方法,取得了不同程度的成功,但没有什么比 SQL 本身更简单了。
作为一个加重因素,我确实需要整个对象(专辑)(或者至少我需要 NumID 和 Name, 不是懒加载)
我试过这个:
/* 1 */
var tmp1 = session.QueryOver<Images>()
.Where(i => i.NumID == ImageID) //The ImageID is for example 1026
.JoinQueryOver(i => i.Album)
.Select(x => x.Album)
.List<Album>();
// Decent to read, but this only loads the NumID from the album
/* 2 */
var tmp2 = session.Query<Images>()
.Join(DBContext.GetQuery<Albums>(), i => i.Albums.NumID, a => a.NumID,
(imgAlias, albAlias) => new {imgAlias, albAlias})
.Where(x => x.imgAlias.NumID == ImageID) //ImageID = 1026
.Select(x => x.albAlias).ToList();
// This one actually works, but it's almost totally unreadable!
应该怎么做?
方式(我主要使用,如果不是唯一的话) - 是使用子查询 (内部SELECT)
// subquery returning the ALBUM ID
var sq = QueryOver.Of<Image>()
.Where(i => i.NumID == ImageID) //The ImageID is for example 1026
.Select(i => i.Album.Id); // here we return the Album.ID (column AlbumID)
// just Albums with searched Image
var query = QueryOver.Of<Album>()
.WithSubquery
.WhereProperty(a => a.Id)
.In(sq)
...
.List<Album>();
最大的优势是,Album
结果 (SELECT) 是 flat (not joined with multi Images)
- 因此我们可以轻松使用分页:
...
.Take(50)
.Skip(50)
.List<Album>();
检查其他一些子查询QueryOver: select columns from subquery