2010-08-25 106 views
1

我想要做這樣的事情...NHibernate的 - 尋呼與的ICriteria和可選的ICriteria調用

return GetSession() 
     .ToPagedList<Employee>(page, pageSize, 
     x=> x.SetFetchMode(DomainModelHelper.GetAssociationEntityNameAsPlural<Team>(), FetchMode.Eager)); 

但我不知道如何將這種Func<ICriteria,ICriteria>傳遞到ISessionICriteria

我有一個標準的分頁擴展方法,這個擴展方法將有一個超載,我可以通過額外的ICriteria方法,以便我可以另外設置FetchMode或其他東西。

擴展方法:

public static class CriteriaExtensions 
{ 
    public static PagedList<T> ToPagedList<T>(this ISession session, int page, int pageSize) where T : Entity 
    { 

     var totalCount = TotalCount<T>(session); 

     return new PagedList<T>(session.CreateCriteria<T>() 
      .SetFirstResult(pageSize * (page - 1)) 
      .SetMaxResults(pageSize * page) 
      .Future<T>().ToList(), page, pageSize, totalCount); 

    } 

    public static PagedList<T> ToPagedList<T>(this ISession session, int page, int pageSize, Func<ICriteria, ICriteria> action) where T : Entity 
    { 
     var totalCount = TotalCount<T>(session); 

     ... 
    } 

    private static int TotalCount<T>(ISession session) where T : Entity 
    { 
     return session.CreateCriteria<T>() 
      .SetProjection(Projections.RowCount()) 
      .FutureValue<Int32>().Value; 
    } 
} 

編輯:

不超載就應該是這樣的:

return GetSession() 
       .CreateCriteria<Employee>() 
       .SetFetchMode(DomainModelHelper.GetAssociationEntityNameAsPlural<Team>(), FetchMode.Eager) 
       .ToPagedList<Employee>(page, pageSize); 

擴展方法:

public static class CriteriaExtensions 
{ 
    public static PagedList<T> ToPagedList<T>(this ICriteria criteria, int page, int pageSize) where T : Entity 
    { 
     var copiedCriteria = (ICriteria) criteria.Clone(); 

     var totalCount = TotalCount(criteria); 

     return new PagedList<T>(copiedCriteria 
      .SetFirstResult(pageSize * (page - 1)) 
      .SetMaxResults(pageSize * page) 
      .Future<T>().ToList(), page, pageSize, totalCount); 
    } 

    private static int TotalCount(ICriteria criteria) 
    { 
     return criteria 
      .SetProjection(Projections.RowCount()) 
      .FutureValue<Int32>().Value; 
    } 
} 

該行var copiedCriteria = (ICriteria) criteria.Clone();聞起來在這裏,但我不知道如何改變這一點。

你會建議哪種方法?

+0

爲什麼不只是做動作( copiedCriteria)? – 2010-08-27 14:03:17

+0

@David Kemp ...我無法追隨你... – Rookian 2010-08-27 21:19:42

回答

0

從我的理解,你試圖從創建它的方法之外修改標準的行爲。

因此,你必須:

public IList<T> GetPageOf<T>(int page, int pageSize, Func<ICriteria,ICriteria> modifier) 
{ 
    return Session.CreateCriteria<T>() 
      .SetFirstResult(pageSize * (page-1)) 
      .SetMaxResults(pageSize) 
      .ToList<T>(); 
} 

所有你需要做的,給修正的機會是對身體改變爲:

return modifer(Session.CreateCriteria<T>) //the modifer gets first dibs on the criteria 
      .SetFirstResult(pageSize * (page-1)) 
      .SetMaxResults(pageSize) 
      .ToList<T>(); 

要知道,改變獲取模式的使用SetFirstResult或SetMaxResults的條件中的多對多和多對一關係可能導致檢索的行數錯誤。

+0

「請注意,在使用SetFirstResult或SetMaxResults的條件中更改多對多和多對一關係的獲取模式可能導致檢索錯誤的行數。」做這件事的另一種方法是什麼? – Rookian 2010-08-31 13:13:43

+0

我明白你的意思了。因爲我正確地理解了你,當我使用內部連接時可能會出現問題,但事實並非如此 – Rookian 2010-09-04 22:10:43

0

有點晚了,但嘿!

做的最簡單的辦法是延長IQueryOver代替的ICriteria,就像這樣:

public static PaginatedList<T> Paginate<T>(this IQueryOver<T, T> instance, int page, int pageSize) where T : Entity { 
    var countCriteria = instance.ToRowCountQuery(); 
    var totalCount = countCriteria.FutureValue<int>(); 

    var items = instance.Take(pageSize).Skip((page- 1)*pageSize).List<T>(); 
    return new PaginatedList<T>(items, page, pageSize, totalCount.Value); 
} 

這將允許你做你的所有預先抓取(他們將在該行數查詢被刪除,但標準將保持不變)。例如:

session.QueryOver<Customer>() 
     .Where(x => x.Status == CustomerStatus.Preferred) 
     .Fetch(x => x.Orders).Eager 
     .Paginate(1, 10); 

將產生兩個SQL查詢,像這樣:

所有項目:

SELECT this_.id, this_.url, order_.sum FROM Customers this_ LEFT OUTER JOIN orders order_ ON this_.id = order_.customer_id WHERE this_.status = 1 LIMIT 10; 

而對於計數:

SELECT count(*) as y0_ FROM Customers this_ WHERE this_.type = 1;