I am working with NHibernate right now, and am coming across a problem trying to improve the data bandwidth efficiency of what im working on.
The context is I am making a data event editor, which has a listview populated with events. These events have 3 types, each is stored in its own MSSQL Table.
There is a parent object, which contains lists of these 3 event types. Originally, I was just selecting all the parents and loading the events underneath it, but if you had say 20 parents, then it would run 60 querys or so to load the list.
I have changed it now to run just 3 querys, one to select all of each event type between date X and date Y. (This date is set with some DateTime pickers on the form).
Now, I am trying to print the name of the parent in the list too, but because I never visited the parent during the nHibernate, I only have a 'proxy' object and it causes a crash. The Parent object has potentially thousands of different objects under it, so I only want to load what I need.
What I have done in the meantime to get it to compile is to visit the object during my nHibernate.
My code to fetch the events is as follows:
public IList<MyEvent> GetAllMyEventForAllParentsFromSpecificTimePeriod(
DateTime startTime, DateTime endTime)
{
using (var session = SessionFactorySingleton.OpenSession())
{
var queryOver = session
.QueryOver<MyEvent>()
.Where(re => re.Time <= endTime)
.And(re => startTime <= re.Time)
.OrderBy(re => re.Time).Desc;
var list = queryOver.List();
if (list.Count > 0)
{
foreach (var myEvent in list.Select(myEvent => myEvent.ParentItem.Name)) { }
}
return list;
}
}
What I have found so far is that the list loads much faster this way.
So I guess the real question here is what can I do to achieve the same thing as where I am visiting each and every ParentItem.Name just to force it to load them?
Updated Answer: I have managed to improve the efficiency thanks to a co-worker.
return session
.QueryOver<MyEvent>()
.Where(re => re.Time <= endTime)
.And(re => startTime <= re.Time)
.JoinQueryOver(x => x.ParentItem)
.List();
The Answer:
foreach (var parent in list.Select(x => x.ParentItem)) { NHibernateUtil.Initialize(parent); }
Which equates to:
public IList<MyEvent> GetAllMyEventForAllParentsFromSpecificTimePeriod(
DateTime startTime, DateTime endTime)
{
using (var session = SessionFactorySingleton.OpenSession())
{
var list = session
.QueryOver<MyEvent>()
.Where(re => re.Time <= endTime)
.And(re => startTime <= re.Time)
.List();
foreach (var parent in list.Select(x => x.ParentItem)) { NHibernateUtil.Initialize(parent); }
return list;
}
}