views:

54

answers:

1

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?

A: 

From my understanding, you're trying to modify the behaviour of the criteria from outside the method that creates it.

Hence you have:

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>();
}

All you need to do to give the modifier a chance is to change the body to:

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

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.

David Kemp
"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." what is an alternative way for doing this?
Rookian
I got what you mean. As I understood you correctly it could be a problem when I would use inner joins, but this is not the case
Rookian