【问题标题】:Even easiest join gets complicated in NHibernate即使是最简单的连接在 NHibernate 中也会变得复杂
【发布时间】:2015-04-22 04:24:23
【问题描述】:

好的,所以我有以下数据库架构

并且关系是一对多的关系(一个相册可以有很多图片)

映射看起来像这样:

<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 更简单了。

作为一个加重因素,我确实需要整个对象(专辑)(或者至少我需要 NumIDName,而不是延迟加载)

我试过这个:

/* 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!

应该怎么做?

【问题讨论】:

  • 您想要找到的相册的所有图片,还是只想要相册的第 1026 张图片?
  • @xantos 不,我只想加载包含 NumID = 1026 图像的相册
  • 你需要这张专辑的图片吗?没有,1026,全部?
  • @xantos 我不需要任何图片,我只需要名称(和 NumID)

标签: c# sql linq nhibernate


【解决方案1】:

方式(我主要使用,如果不是唯一的话) - 是使用子查询 (内部选择)

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

【讨论】:

  • 查询中的 Of 是什么?
  • 嗯,这就是你应该能够在 VS 中快速找到的内容,对吧?这是一个返回 Detached QueryOver...(分离条件)的 static 方法。这些与任何会话无关。它们是虚拟的。我们可以通过这种方式构建我们想要的任何查询.. 但最后,我们必须将它们绑定到会话,或者将它们用作子查询......请检查 DOC:nhibernate.info/doc/nh/en/…nhibernate.info/doc/nh/en/index.html#queryqueryover-subqueries
  • 好的。我明白了,它似乎工作。即使您不需要加载整个对象,这也是您解决问题的方法吗?我的意思是,有没有更好的方法在 NHibernate 中编写一个简单的连接?
  • 在我发给你的链接中,你可以找到很多方法。但总的来说我会说(我确实用这种方式) 1) 多对一 应该被连接,并且应该更好地投影(只选择所有连接表中的列)2) 一对多 - 从不连接。始终通过 subqery 进行过滤,然后使用普通/扁平根对象。 NHibernate 将加载所需的集合广告。检查这个:transformer for projections 和那个improve lazy loading ...享受可能的 NHibernate
  • 你知道吗?尝试搜索 NHiberante 多对多,不要使用它......你会发现我的名字everyhwere:stackoverflow.com/a/22563990/1679310stackoverflow.com/a/16827671/1679310......所以不要使用多对多。要回答你的问题......它应该被视为一对多......但是......(这里有更多链接stackoverflow.com/a/21136089/1679310不使用多对多;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多