Showing posts with label NHibernate. Show all posts
Showing posts with label NHibernate. Show all posts

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

Monday, March 9, 2009

Handling Cartesian Products in NHibernate

I have been using NHibernate for a little while now, but I am mostly self taught in this. I have recently done a course on ADO.NET to try and understand some of the basics of data access that I may have missed, and also to get a little of an understanding of the core technologies behind NHibernate.

I was reading a post on Eager Loading by Derik Whittaker on the Devlicio.us site where Derik was talking about returning a list of objects using the CreateCriteria query method. His issue was that when he used Eager Loading, he got more rows back then expected. This was due to the Cartesian Product issue where the join on the tables caused extra rows to be returned for a single object and NHibernate hydrating an object for each row. His solution was to include the command:

.SetResultTransformer( new DistinctRootEntityResultTransformer() )

which can be shortened to:

.SetResultTransformer(CriteriaUtil.DistinctRootEntity)

While reading through the comments on this post I found that someone had posted:

Why didn't you use the CreateMultiCriteria method?

This got me thinking. I have heard of MultiCriteria before but never realised that you could use it to solve the Cartesian Product problem before.

So to Google I went and I found the NHibernate Documentation and to my surprise I found the example under CreateMultiQuery. I had never found this before because I had always limited my reading to the CreateMultiCriteria (which is a more fluent version of MultiQuery).

So now the challenge I have set myself is to sit down and try to get some examples of this working.

Till next time.

Erik