I want to do something like this...
return GetSession()
.ToPagedList<Employee>(page, pageSize,
x=> x.SetFetchMode(DomainModelHelper.GetAssociationEntityNameAsPlural<Team>(), FetchMode.Eager));
But I don't know how to pass this Func<ICriteria,ICriteria>
into the ISession
or ICriteria
.
I have a standard paging extension method and this extension method shall have an overload where I can pass additional ICriteria methods, so that I can additionally set up the FetchMode
or something else.
Extension Method:
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;
}
}
edit:
Without an overload it would look like this:
return GetSession()
.CreateCriteria<Employee>()
.SetFetchMode(DomainModelHelper.GetAssociationEntityNameAsPlural<Team>(), FetchMode.Eager)
.ToPagedList<Employee>(page, pageSize);
Extension Method:
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;
}
}
The line var copiedCriteria = (ICriteria) criteria.Clone();
smells here, but I don't know how to change this.
Which approach would you suggest?
From my understanding, you're trying to modify the behaviour of the criteria from outside the method that creates it.
Hence you have:
All you need to do to give the modifier a chance is to change the body to:
Be aware, that changing the fetch-mode for many-to-many and many-to-one relationships in criteria that used SetFirstResult or SetMaxResults can result in the wrong number of rows being retrieved.
A bit late, but hey!
The easiest thing to do is to extend IQueryOver instead of ICriteria, like so:
This will allow you to do all your eager fetching (they will be removed in the row count query, but the criterias will remain the same). Example:
Will yield two sql queries, like this:
For all items:
And for the count: