2010-08-25 2 views
1

я хочу сделать что-то вроде этого ...NHibernate - пейджинг с ICriteria и опциональный ICriteria называет

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

Но я не знаю, как передать эту Func<ICriteria,ICriteria> в ISession или ICriteria.

У меня есть стандартный метод расширения подкачки, и этот метод расширения должен иметь перегрузку, где я могу передавать дополнительные методы 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)? –

+0

@ Давид Кемп ... Я не могу следовать за тобой ... – Rookian

ответ

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

+0

Я понял, что вы имеете в виду. Поскольку я правильно понял вас, это может быть проблемой, когда я буду использовать внутренние соединения, но это не так – Rookian

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;