Tuesday, March 17, 2009

Layer Transparent Paging

I am currently working on an issue where I am processing large amounts of data. So I have decided to implement a paging strategy.

Now my issue was that I am wanting to pass this paging strategy from my Data Access Layer (DAL) to my Buisness Logic Layer (BLL) without exposing my underlying framework which happens to be NHibernate.

So I have devised the interface:

public interface IPagedResult<T> : IEnumerator<IList<T>>
{
int PageSize { get; }
IPageSession Session { get; }
}

This I can then pass through to my BLL to iterate through the results like so:

using (var pagedResults = DAL.GetPagedResultsForSomething())
{
while (pagedResults.MoveNext())
{
foreach (var item in pagedResults.Current)
{
doSomethingWithItem(item);
}
}
}


Allowing the PagedResult object to handle all session and transaction issues.

I also devised a way to put my query into the PagedResult object using Lambdas:

public class PagedResult<T> : IPagedResult<T>
{
private int currentResult = 0;
public delegate ICriteria QueryFunction(ISession session);

public PagedResult(int pageSize, ISession session, QueryFunction query)
{ ... snip ... }

public vool MoveNext()
{
try
{
Current = query(session)
.SetFirstResult(currentResult)
.setMaxResults(PageSize)
.List<Statement<T>();

if ((Current == null) (Current.Count == 0))
{
Current = null;
return false;
}

currentResult += PageSize;
return true;
}
catch
{
session.Transaction.RollBack();
throw;
}
}

... snip ...
}


This allows me to use it as such:

var statementId = 1;
var pageSize = 10;
new PagedResult<Statement>(
pageSize,
new Session(),
s =>
s.CreateCriteria(typeof(Statement), "statement")
.SetResultTransformer(CriteriaUtil.DistinctRootEntity)
.Add(Restrictions.Eq("statement.Id", statementId))
);
What do people think?

Cheers,

Erik

No comments:

Post a Comment