Downloads
About the Sample Project
The sample project includes a SQL script for creating the DB. The extra tables and data are included for use in further articles. Also, you may wish to visit
http://www.castleproject.org/activerecord/index.html for more information and downloads. The sample is based on the application ActiveRecord introduction post, with modifications for the new features.
Lazy Loading
One of the finer points to look out for in Active Record is the traffic to and from your database server. ActiveRecord has added a pretty seamless data persistence layer to your application, but that doesn’t mean that you should just take it for granted that all is well in the transportation of your data.
The inclusion of the log4net library in the project allows ActiveRecord/NHibernate to give you information regarding the SQL queries travelling to the server. In the previous post (here), when the application starts, you may notice in your output window (or log4net destination) that there are multiple SELECTs made to the TelephoneNumber table. This is essentially fetching all the child records for the Contact objects, which in this case aren’t really needed up front.
Having a look at the Contact.cs file, I've included additional information in the attributes:
71 [HasMany(typeof(TelephoneNumber), ColumnKey = "ContactId", Lazy=true)]
You'll notice the additional parameters, most importantly the Lazy=true part. This allows for this collection to be fetched only when needed. The collection is only fetched once, and then cached for further use.
This isn't the only change that is needed to make use of the lazy loading, though. You need to use the SessionScope object in the form go glue things together.
Session Scope
In the MainForm.cs file, I've added a private variable:
17 private SessionScope _sessionScope;
This is used to keep the session scope variable alive for the scope of the form. In addition, I've added a line to the top of the Form_Load event
private void MainForm_Load(object sender, EventArgs e)
{
//This will keep this session scope for the scope of this form
_sessionScope = new SessionScope();
//Bind the list view to a contact list
ContactsListBox.DisplayMember = "FriendlyName";
ContactsListBox.DataSource = ContactFactory.GetList();
}
This gets a new session scope and assigns it to our local variable. That's where the modifications end. If you run the new application, you'll notice in the output window that the SELECT statement for the child collection is only run when you change the selected item in the list box, i.e. When the collection is used to populate the grid.
You may be wondering why the introduction of the session scope is necessary - In short, the SessionScope is necessary to extend the scope of the NHibernate ISession, so that when it is checked, an instance is available (refer here). Lazy loading for objects has to take place on the same session that the parent object was created in. If the code for the session scope is removed from the form, you will get a "Failed to lazily initialize a collection - no session" error.