2

我在Nhibernate QueryOver中查詢,它帶回了一個情節對象(情節是一個照顧的咒語)的集合,而集合對象又集中了情節狀態作爲每個情節的屬性。不過,我想改變這一點,以便每個情節只會帶回該情節的最新狀態更新,而不是所有情節。NHibernate QueryOver子查詢只返回最新的記錄

做到這一點的SQL如下:

SELECT * 
FROM DIPEpisode e 
INNER JOIN DIPEpisodeStatus s on s.EpisodeID = e.SequenceID 
WHERE e.ClientID = '1000001' 
AND s.SequenceID IN (
SELECT TOP 1 SequenceID 
FROM DIPEpisodeStatus s 
WHERE s.EpisodeID = e.SequenceID 
ORDER BY StatusRecordedDate DESC 
) 

我寫了下面的查詢,給了我幾乎正是我需要的

var statuses = 
      QueryOver.Of<DIPEpisodeStatus>() 
      .OrderBy(x => x.StatusRecordedDate).Desc 
      .Select(x => x.Id).Take(1); 

DIPEpisodeStatus statusAlias = null; 

     return 
      session.QueryOver<DIPEpisode>() 
      .JoinQueryOver(x => x.DIPEpisodeStatuss,() => statusAlias) 
      .Fetch(x => x.AgencyID).Eager 
      .Fetch(x => x.DIPEpisodeStatuss).Eager 
      .Where(e => e.ClientID.Id == this.clientId) 
      .WithSubquery.WhereProperty(x => x.Id).Eq(statuses) 
      .List(); 

這將生成以下SQL:

SELECT * 
FROM DIPEpisode this_ 
    inner join DIPEpisodeStatus statusalia1_ 
    on this_.SequenceID = statusalia1_.EpisodeID 
WHERE statusalia1_.ClientID = '1000001' /* @p0 */ 
    and statusalia1_.SequenceID = (SELECT TOP (1 /* @p1 */) this_0_.SequenceID as y0_ 
            FROM DIPEpisodeStatus this_0_ 
            ORDER BY this_0_.StatusRecordedDate desc) 

正如您所看到的,唯一缺少的是子查詢中的where子句。爲了生成這個額外的where子句並僅回退最近的狀態更新,我需要對查詢進行哪些更改?

感謝

回答

3

收集DIPEpisodeStatuss總是與所有實體初始化,因爲它會破壞否則changetracking。你可以爲集合定義一個過濾器或者用你想要的返回一個DTO。此外,由於無法在一個sql語句中加載和過濾,因此將忽略該提取。

NHibernate filters are explained here

defining Filters in FNH

它將如何用DTO

// assuming SequneceID and StatusRecordedDate correlates 
var subquery = QueryOver.Of<DIPEpisode>() 
     .Where(e => e.ClientID.Id == this.clientId) 
     .JoinAlias(e => e.DIPEpisodeStatuss,() => statusAlias) 
     .Select(Projections.Max(() => statusAlias.SequenceID)); 

// or as in question 
var subquery = QueryOver.Of<DIPEpisode>() 
     .Where(e => e.ClientID.Id == this.clientId) 
     .JoinAlias(e => e.DIPEpisodeStatuss,() => statusAlias) 
     .OrderByDescending(() => statusAlias.StatusRecordedDate) 
     .Select(() => statusAlias.SequenceID) 
     .Take(1); 

DIPEpisodeDto dto = null; 
DIPEpisodeStatus statusAlias = null; 
return session.QueryOver<DIPEpisode>() 
     .Where(e => e.ClientID.Id == this.clientId) 
     .JoinQueryOver(e => e.DIPEpisodeStatuss,() => statusAlias) 
     .WithSubquery.WhereProperty(estatus => estatus.Id).Eq(statuses) 
     .SelectList(list => list 
      .Select(e => e.Whatever).WithAlias(() => dto.Whatever) 
      .Select(() => statusAlias.SquenceId).WithAlias(() => dto.StatusId) 
      ... 
     ) 
     .TransFormUsing(Transformers.AliasToBean<DIPEpisodeDto>()) 
     .List(); 

使用LINQ

var query = from e in session.Query<DIPEpisode>() 
      from s in e.DIPEpisodeStatuss 
      where e.ClientID.Id == this.clientId 
      where s.Id == (
       from e2 in session.Query<DIPEpisode>() 
       from s2 in e2.DIPEpisodeStatuss 
       orderby s2.StatusRecordedDate descending 
       select s2.Id) 
       .First() 
      select new DIPEpisodeDto 
      { 
       e.Prop1, 
       Status = s, 
      }; 
return query.List<DIPEpisodeDto>(); 
+0

完成或者我去修改返回的DTO的路線。我穿過每個epiodde dto,然後訂購epsiode狀態並查找第一條記錄,然後將其設置爲epsode狀態集合。 – 2012-03-13 13:38:21

+0

這將加載所有stati或者是SELECT N + 1,其中N是Episode集合的計數 – Firo 2012-03-13 15:49:51