vrijdag 27 juli 2007

NHibernate & MS Access: problems with autonumber fields

I was playing around with NHibernate and MS Access a bit the other day, and I ran into an annoying problem.

When I tried to save an object which maps to a table wich has an 'autonumber' field, I received this error:

a different object with the same identifier value was already associated with the session: 0

It looked like NHibernate was unable to retrieve the ID that has been given to the new record in the database.

So, I decided to set up log4net to see if I could find any clue in the logs about the reason for this problem.

As it turned out, it seems that NHibernate was closing the database-connection between the INSERT and the SELECT @@identity statements.

DEBUG NHibernate.SQL - INSERT INTO table ...
DEBUG NHibernate.Connection.DriverConnectionProvider - Obtaining
IDbConnection from Driver
DEBUG NHibernate.Impl.BatcherImpl - Closed IDbCommand, open IDbCommands: 0
DEBUG NHibernate.Impl.ConnectionManager - aggressively releasing
database connection
DEBUG NHibernate.Connection.ConnectionProvider - Closing connection
DEBUG NHibernate.Impl.BatcherImpl - Opened new IDbCommand, open IDbCommands: 1
DEBUG NHibernate.Impl.BatcherImpl - Building an IDbCommand object for
the SqlString: select @@identity
DEBUG NHibernate.SQL - select @@identity

After some research in the Hibernate documentation and on the Internet, I discovered that this is caused by the 'connection release mode'.

The default connection release mode seems to release the connection after each SQL statement, so obviously, Access is not able to determine the correct ID of the last inserted record, since the select @@identity command must be executed on the same connection as its related INSERT statement.

Now that we know what caused this problem, it is easy to fix it: just make sure that you do not use the default connection release mode when using NHibernate with MS Access.

To do so, you should specify the connection release mode in your NHibernate configuration file like this:

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="hibernate.connection.release_mode">on_close</property>
</session-factory>
</hibernate-configuration>

More information regarding the different options / settings for the connection-release mode can be found here.

woensdag 18 juli 2007

Counting in SQL Server: SELECT COUNT(*) != SELECT COUNT(columnname)

Today, I've learned something new; or rather, I was being pointed out something that I didn't know about:
It seems that, doing a SELECT COUNT(columnname) does not always give you the same results as doing a SELECT COUNT(*). As it was pointed out to me, doing a SELECT COUNT(columnname) returns the number of rows in the resultset in where the value of the field in 'columnname' is NOT NULL.

This means that, given the following set of data:

idname
1Name1
2NULL
3Anothername

performing this statement:

SELECT COUNT(*) FROM table
gives us 3 as a result, while doing this:
SELECT COUNT(name) FROM table
returns 2 as result.

I really was ignorant to this behaviour, as I do (or did), most of the time a SELECT COUNT(1) FROM table instead, since I thought that this was the most performant option, but this also seems to be not true in some circumstances;
doing a SELECT COUNT(*) enables SQL Server to use indexes in calculating the number of results in a resultset.

For a more thourough article about this, I'd like to refer to this article on SQL Server Central.

Thanks to Peter De Boer for pointing this out

maandag 18 juni 2007

Dependency Injection versus Service Locators

When I was driving home from work, I have been thinking: when an object (entity) needs a reference to a repository for instance, to get some work done, how do you get a reference to that dependency (in this case, the repository) ?
Do you use dependency injection, or do you use a service locator ? When to choose what ? What are the advantages / disadvantages over both approaches ?

For example, suppose you have a 'Customer' class; this class has a property 'Status' which says whether the Customer is a 'Gold Customer', a 'Badly Paying Customer' or a 'Normal Customer'.
In order to determine to which 'state' a specific Customer belongs to, it might be necessary to retrieve some information out of a datastore. In this case, it could be necessary for instance to retrieve some invoice information regarding this customer.
(A Gold Customer for instance, is a Customer who has ordered for a specific amount of goods in a certain period, while a Bad Payer might be some-one who has overdue invoices).
So, a reference to an instance of IInvoiceRepository must be given to the Customer object.
The question now is, how do you give this dependency to the Customer object ?

Do you use 'Dependency Injection', and give this dependency via a constructor or a property to the Customer instance, like this:

Customer c = customerRepository.GetCustomer (5);
c.InvoiceRepository = repositoryFactory.CreateInvoiceRepository();

Or, should you leave this responsability to the Customer object ? In other words: let the Customer instance search for the correct IInvoiceRepository using a service locator. This could then be done in the Status property of the Customer class:

public CustomerStatus Status
{
get
{
IInvoiceRepository ir = DomainSettings.Instance.RepositoryLocator.GetInvoiceRepository();
...
return status;
}
}

In this case, the 'RepositoryLocator' can decide which implementation of IInvoiceRepository it has to create and return based on a value in a config file for instance.

Anyway, when do you choose for which option ? What are the advantages /disadvantages of both concepts ? In which situation do you favor the one over the other ?

I hope that some smart people can enlighten me about this matter. :)

maandag 30 april 2007

NHibernate Session Management in Domain Driven App's

As I've posted earlier, Billy McCafferty has written an excellent article on using NHibernate within ASP.NET applications.
In this article, he describes how to use the 'Open Session in View' pattern. This is perfectly useable and a very clean way of working with NHibernate in a DDD ASP.NET application, unfortunately, it is -imho- less (or not) useable in a WinForms application.
The 'Open Session in View' pattern implies that a new NHibernate ISession object is created at each request, and closed at the end of each request. (Changes are committed as well).

It is very important that the Repositories keep their hands off of Transaction Management. In other words: a repository should not start, commit or rollback a transaction. This is natural, since the repository doesn't know anything of the 'context' of the Unit of Work. Therefore, transaction managment should be a responsability of the client (the UI, the Service layer, whatever).
To achieve this, Billy stores the current ISession in the CallContext or HttpContext (he has made abstraction of which implementation is used offcourse. CallContext is used in the case of a WinForms app or a Unit-Test project, HttpContext is used in case of an ASP.NET app; see the source-code that accompagnies the article for more details).
In this way, the repositories can easily access the current ISession when they need it by just getting it out of the CallContext or HttpContext, and the ASP.NET application (the ASP.NET webpages) have access to the ISession as well, so they can start, commit and rollback the unit-of-work.
This is the ideal solution in ASP.NET, since you only need one 'ISession' on each request. At the end of the request, the Session can be closed (committed / rollbacked), so they're short-lived, and this is perfect.

However, in a WinForms application, you'll probably want more then one 'Unit of Work' at the same time, and therefore, have more then one open ISession at the same time.
An example will clarify this a bit more:

Suppose you've a WinForms application which consists of a form which lists all Customers. You can edit a customer by double-clicking it; a 'Customer-Detail' form will open up, where you can make changes to the Customer.

Now, what happens if you edit a Customer ? You'll retrieve the ISession from the CallContext, load the Customer from the DB, make some changes and confirm the changes; closing the form will close the ISession.
So far, no problem. However, what happens if you open another Customer-Detail form before you've committed the changes to the first Customer ?
What if you have 2 Customer Detail Forms open, make changes to Customer 1, save the changes and close the form. Afterwards, you want to save the changes to Customer 1... The problem now is that you've closed the ISession when you've closed the first Customer-Detail form. Customer 2 was attached to the same session which is now closed. If you want to save the changes to customer 2, you'll need an ISession, so you'll require a new ISEssion in this case. Then, NHibernate will think that Customer 2 is a new Customer, and will try to insert a new record to the DB where in fact, the existing Customer needs to be updated.

In my opinion, it is better to have a seperate Unit Of Work (ISession) for each instance of the CustomerDetail form in this case.
This implies that you should create a new ISession for each instance of the CustomerDetail form: this means that the ISession cannot be kept in the CallContext since otherwise, each form would share the same ISession.
Then... how should this be solved ? In my humble opinion, the best way to solve this is to create an ISession when an instance of a form is created, pass it to the repositories, and use it to handle the transaction(s) in the form:

public class CustomerDetailForm : Form
{
private ISession _unitOfWork;

private CustomerRepository _custRep;

private Customer _customer;

public void ShowCustomer( int customerId )
{
_unitOfWork = AppSettings.Instance.SessionFactoryObj.OpenSession();

_custRep = new CustomerRepository(_unitOfWork);

_customer = _custRep.GetCustomer(customerId);

// Disconnect from the DB, since we do not need DB action at this time
// anymore.
_unitOfWork.Disconnect();

}

public void OKButton_Click(object sender, EventArgs e )
{
// Reconnect to the DB
_unitOfWork.Reconnect();

ITransaction tx = _unitOfWork.BeginTransaction();
_custRep.Save (_customer);
tx.Commit();
}
}

I don't know if there's any better / cleaner way of doing this... If you know one, please let me know. :) It is offcourse cleaner if you could abstract the use of NHibernate's ISession by creating a class which encapsulates the ISession, but I wanted to keep things a bit sparse. :)

vrijdag 27 april 2007

Article: NHibernate best practices with ASP.NET

Billy McCafferty has written an excellent article on NHibernate and Domain Driven Design. It can be found here on the CodeProject.
Although it is focused on using NHibernate in ASP.NET, it is still very interesting even if you do not develop in ASP.NET. He talks about a few key concepts in DDD, and the example code is also very interesting.
There's one little drawback however in his example code: although he mentions that the way of working he demonstrates should work for Winforms development as well, I do not completely agree on that. However, I've to investigate it a bit more, which I'll do as soon as I find some time. Once done, I'll post my findings offcourse.

zondag 22 april 2007

Split

When I started this weblog in december 2005, I decided to blog about software development and about photography.

Now, 1 and a half year later, it seems to me that this was not such a good idea; I feel that software engineering and photography do not share the same audience.
Now, you probably think, did it really take you that long to acknowledge this fact ? Well, not really: during the first few months of blogging, the number of photography posts here was pretty low. At this time, I've noticed that 3 out of the 5 last posts were tagged with 'photography', so that's why I've finally decided to split things up.

This will remain my weblog that is focussed on programming (notice that I've changed the name from 'weblog' to 'devlog' as well :) ). Things that are focused on photography will appear on my photolog, so if you're interested, you can have a look there :).

I've choosen Wordpress to host my photo-blog, since Wordpress allows me to import posts from blogger, and that's what I've done: I've imported all the 'photography-tagged' posts from this weblog in my wordpress photo-blog, and translated them to dutch.

vrijdag 13 april 2007

.NET 1.1: Problems when selecting rows from a DataTable using an aggregate filter

I came accross a rather weird error today when I was working in C# 1.1. I was trying to select the records that exist in a DataTable that had more then one child in a related datatable.


To make things a little bit more clear, I've reproduced this by creating a Typed Dataset which contains 2 tables from the Northwind database:



What I want to do, is to select the Categories for which there are multiple products classified into.
So, this is what I've done; I created an instance of this dataset, and populated it with some data:

NorthwindDS ds = new NorthwindDS();
NorthwindDS.CategoriesRow c1 = ds.Categories.NewCategoriesRow();
c1.CategoryID = 1;
c1.CategoryName = "Category 1";
ds.Categories.AddCategoriesRow (c1);

NorthwindDS.CategoriesRow c2 = ds.Categories.NewCategoriesRow();
c2.CategoryID = 2;
c2.CategoryName = "Category 2";
ds.Categories.AddCategoriesRow (c2);

NorthwindDS.ProductsRow p1 = ds.Products.NewProductsRow();
p1.ProductID = 1;
p1.CategoryID = 1;
p1.ProductName = "Product 1";
ds.Products.AddProductsRow (p1);

NorthwindDS.ProductsRow p2 = ds.Products.NewProductsRow();
p2.ProductID = 2;
p2.CategoryID = 1;
p2.ProductName = "Product 2";
ds.Products.AddProductsRow (p2);

// The following line is important to illustrate the problem :)
ds.AcceptChanges();

This is pretty simple, I've just populated the Dataset with 2 categories and 2 products, and the 2 products are both linked to Category 1.
Now, the Query I've talked about earlier should thus return 1 Category, specifically, Category 1, since there's more then one product related to this category.
I do this using the following code:

string filterExpression = "COUNT (Child.CategoryID) > 1";
DataRow[] dr = ds.Categories.Select (filterExpression);

foreach( NorthwindDS.Category cat in dr )
{
Console.WriteLine (cat.CategoryName);
}

This gives me the expected result, it writes 'Category 1' to the output-window.
However, suppose that I've populated this Dataset with data coming from the Database, and that I add a product - record to this Dataset after the Dataset has been populated...
I can simulate this by adding a ProductRow to the DataSet after the 'AcceptChanges()' call:


// previous lines which create the dataset, and add the categories
// and the first 2 products are left out for brevity
ds.AcceptChanges();

NorthwindDS.ProductsRow p3 = ds.Products.NewProductsRow();
p2.ProductID = 3;
p2.CategoryID = 1;
p2.ProductName = "Product 3";
ds.Products.AddProductsRow (p3);

filterExpression = "COUNT (Child.CategoryID) > 1";
DataRow[] dr = ds.Categories.Select (filterExpression);

foreach( NorthwindDS.Category cat in dr )
{
Console.WriteLine (cat.CategoryName);
}

Now, I would expect that this gives me the exact same result as before, however, I get an exception:

An unhandled exception of type 'System.Data.VersionNotFoundException' occurred in system.data.dll

Addition information: There is no original data to access.

Probably, .NET wants to access the original contents of my new ProductRow, but since it is a new one, it has no Original DataViewRowState ...
I've tried to work around this by specifying that the CurrentRows should be used:

ds.Categories.Select (filterExpression, 
string.Empty,
DataViewRowState.CurrentRows);

But, to no avail. (Which didn't surprise me, because this line just says: return the Current DataViewRowState of the Categories and the problem seems to occur when the Product datarows are accessed).

So, this seems to be a bug in the .NET 1.1 (I've tried this in .NET 2.0 as well, and there, it works like a charm).

So, is there anybody who knows how to solve or work around this issue ?

zondag 1 april 2007

Tagliatelle - scampi

Tagliatelle - Scampi

vrijdag 9 maart 2007

Oudenaarde by Night

Yesterday evening, I've been walking around in Oudenaarde - the city were I'll be living in in the near future -, and I've taken these photographs.

oudenaarde stadhuis

oudenaarde walburga carillon

zondag 25 februari 2007

DDD: implementing persistence using NHibernate

Introduction

At last, I've found some time to sit down and begin writing what should be the last part of this 'Domain Driven Design Quickstart' series of articles. In this final article, I will implement the persistence of the domain model that I’ve created in the previous parts of this series. (part I, part II and part III).

To implement the persistence functionality of the domain model, I will use an O/R mapper. I’ve opted to use NHibernate as O/R mapper for this project.
I will not make an in-depth coverage of NHibernate in this article, since this is a bit beyond the scope of this article. Besides, there are various excellent resources on (N)Hibernate available. The book Hibernate in Action, for instance, is an excellent resource to learn about (N)Hibernate, and it offers also some more insights in the O/R principle.


The Database Schema

To get the information in a database, we need a database first (clever :) ). So, I’ve created this ERD:



I’m not going to elaborate on this database-schema since I presume that you have enough knowledge of databases / database-modelling, etc… So lets hop to the next phase.

NHibernate configuration

NHibernate is an O/R mapper which lets you persist your data to a number of supported databases. To be able to use it however, it needs to be setup properly; in .NET this can be easily done in the configuration file of your project.
For this project, I’ll create a WinForms application, and I’ll make some changes to the app.config file to configure NHibernate. This is done like this:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="nhibernate"
type="System.Configuration.NameValueSectionHandler,
System, Version=1.0.5000.0,Culture=neutral,
PublicKeyToken=b77a5c561934e089"/>
</configSections>
<nhibernate>
<add key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider"/>
<add key="hibernate.dialect"
value="NHibernate.Dialect.MsSql2000Dialect"/>
<add key="hibernate.connection.connection_string"
value="Data Source=localhost;
Initial Catalog=SomeShop;
Integrated Security=SSPI"/>
</nhibernate>
</configuration>

As you can see, I need to define the nhibernate configuration section first. Once this is done, I specify to which type of database NHibernate will have to talk to (SQL Server 2000), and I also specify the connection string that must be used.

If you use Microsoft Visual Studio.NET 2005, you might come across some unwanted error/information messages concerning the nhibernate config section. I’ve written another post about this problem, and how to solve it a while ago. You can read it here.

Now we’ve configured our project to use NHibernate, but we also need to tell NHibernate how our classes should be mapped to our database-schema. This can be done by creating NHibernate mapping files which describe how a class should be represented in the database. Those mapping files are nothing more then XML files. As I’ve said earlier, this is not an NHibernate tutorial, but merely an article on how NHibernate can be incorporated in a Domain Driven Design project. Therefore, I will not post all the mapping files here or explain them in detail. I will post 2 mapping files here however, and explain them a bit.

NHibernate mapping files

For each class in my domain model, I create an NHibernate mapping file in my Visual Studio.NET project which contains my business classes.
In this specific case, I have a Class Library project which contains the ‘Customer’, ‘Order’, ‘OrderLine’, etc… business classes, so it is in this class library that I also create the NHibernate mapping files.

The mapping file for the Order class, for instance, looks like this:

<xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="SomeShopDomain.Order, SomeShopDomain"
table="[Order]" lazy="false">
<id name="Id" column="OrderId" type="Int32"
unsaved-value="-1"
access="field.camelcase-underscore">
<generator class="identity" />
</id>
<property name="OrderDate" column="OrderDate"
access="field.camelcase-underscore" />
<property name="Status" column="OrderStatus"
access="field.camelcase-underscore" />
<property name="Discount" column="Discount"
access="field.camelcase-underscore" />

<many-to-one name="OwningCustomer" column="CustomerId"
class="SomeShopDomain.Customer, SomeShopDomain"
not-null="true"
access="field.camelcase-underscore"
/>

<bag name="OrderLines" cascade="save-update"
inverse="true"
access="field.camelcase-underscore">
<key column="OrderId" />
<one-to-many class="SomeShopDomain.OrderLine, SomeShopDomain"/>
</bag>

</class>
</hibernate-mapping>

This is not the most simple mapping-file in the project, since the Order class contains a collection of OrderLines, so this relationship is reflected in the mapping file.

But, it is maybe better if I just explain the complete mapping file a bit .

As you can see at the beginning of the file, this file describes how the Order class should be mapped to the Order table in the database.
The 'id' element tells NHibernate that the Id property of the class should be used to identify each Order. This element also defines that the Id property of the class maps to the OrderId column in the Order table. The data-type is also defined in there, and it is stated that instances of the Order class that have a value of -1 for the Id property, are New/transcient (unsaved).
Now, NHibernate will use the Id property of the Order class to get or set the value of the Id.
This however, has some disadvantages in my opinion: what if you have some specific logic in the setter-part of the property, some validation-logic for instance ? When NHibernate loads an object out of the database, should this logic be executed ? In my humble opinion not. When an object is loaded from a persistent state, the values of the object must be set, without performing any extra logic.
Another problem pops up when the property is read-only. In this case, Id is an 'identification', and the programmer that uses the Order class, shouldn't be able to change this property. Therefore, this property has only a getter in the Order class, and no setter. NHibernate will have a problem with that: it will throw an exception saying that it cannot set the value of the Id property since it has no setter.
That's why I use the access attribute. With this attribute, I tell NHibernate that it should use the field instead of the property, and that it can find this field by taking the property-name that I've defined in the mapping file, prefix it with an underscore, and make the first character lowercase.
So, in this case, instead of setting the Id property, NHibernate will look for a field in the Order class which is called _id and give this field the value of the OrderId column. By using the field instead of the property, I'm always sure that no extra logic will be executed, and I do not have to bother with getter-only properties.
You can read more about this here and here Particulary in the comments of these articles.
The following three properties are quite straightforward. These elements just say to which column each property maps, and I've also defined that NHibernate should use the field instead of the property to get / set these properties.

The next two elements are bit more interesting though.
The many-to-one element defines how the relationship between Order and Customer must be saved. As you might remember, the Order class holds a reference to the Customer to which the order belongs. To be able to populate the OwningCustomer property which contains this reference, and to be able to save the link with the Customer when the Order is saved, the many-to-one element is used. A Customer can have many Orders, and an Order always belongs to one Customer. The many-to-one element just says that the OwningCustomer property maps to the CustomerId column in the Order table, and that the OwningCustomer is of the type SomeShopDomain.Customer. By defining this type, NHibernate knows that it should look for a mapping file which should be called SomeShopDomain.Customer.hbm.xml in where the mapping of the Customer type is defined.
Mapping files should be named after the class for which they contain the mapping, and should have the extension hbm.xml. Next to that, you also have to specify 'embedded resource' as build action for the mapping files.
The <bag> element defines that the Order contains a collection of OrderLines, and that these objects must be of type SomeShopDomain.OrderLine. NHibernate will use the mapping-file of the OrderLine class to determine in which table those OrderLines must be saved.
The <key> element states that the Id of the current Order must be saved in the OrderId column of the table where the OrderLines will be saved.


This concludes the quick tour of the NHibernate mapping file. For more information about the possible elements, I'll refer to the Hibernate in Action book, or to the Hibernate documentation.

The mapping file of the OrderLine class, looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="BlogShopDomain.OrderLine, BlogShopDomain"
table="OrderLine" lazy="false">
<id name="Id" type="Int32"
column="OrderLineId"
unsaved-value="-1"
access="field.camelcase-underscore">
<generator class="identity" />
</id>
<property name="ArticleName" column="ArticleName"
access="field.camelcase-underscore" />
<property name="ArticlePrice" column="ArticlePrice"
access="field.camelcase-underscore" />
<property name="ArticleId" column="ArticleId"
access="field.camelcase-underscore" />
<property name="NumberOfItems" column="NumberOfItems"
access="field.camelcase-underscore" />

<many-to-one name="OwningOrder" column="OrderId"
class="BlogShopDomain.Order, BlogShopDomain"
access="field.camelcase-underscore"
not-null="true" />

</class>
</hibernate-mapping>
I'm not going to elaborate on this file, so lets get to the next part. :)

Integrating NHibernate in the project

At this point, I've done some necessary configurations, but some coding needs to be done as well.
NHibernate uses the concept of Sessions as an 'interface' between your objects and the database. A session can be considered as a unit of work. This is a bit a simplistic definition, but you can find a better one in the Hibernate documentation or in Hibernate in Action.
To be able to create Sessions, you'll need a SessionFactory. Unlike Hibernate Sessions, a SessionFactory is an expensive object to instantiate, so it's best practice to create this object only once.
Therefore, I like to create a Singleton class which holds amongst some other stuff, the NHibernate ISessionFactory:

public class ApplicationSettings
{
private static ApplicationSettings _instance;

private ApplicationSettings() {}

// The only access point to the ApplicationSettings instance.
public static ApplicationSettings Instance
{
get
{
if( _instance == null )
{
_instance = new ApplicationSettings();
}
return _instance;
}
}

private ISessionFactory _sessionFactory = null;

public ISessionFactory SessionFactoryObj
{
if( _sessionFactory == null )
{
Configuration cfg = new Configuration();
cfg.AddAssembly (typeof(SomeShopDomain.Customer).Assembly);
_sessionFactory = cfg.BuildSessionFactory();
}
return _sessionFactory;
}

}

This structure guarantees that I'll have only one ISessionFactory in my project, and that this SessionFactory is created only once.
The code to create the ISessionFactory is quite simple; first of all a Configuration object is instantiated, and the assembly which contains the business classes is added to the Configuration. As you can see, I use reflection to find that assembly, since I don't want to be bothered with assembly-names and locations. After that, the BuildSessionFactory method is called which creates the ISessionFactory.
This ApplicationSettings class is not part of my class library which contains the domain, but belongs to the project that contains my client application (in this case, a WinForms application). More on that later.
At this time, we can create ISessions.

ISession s = ApplicationSettings.Instance.
SessionFactoryObj.OpenSession();

Creating Repositories for our Domain classes

In Domain Driven Design, getting objects from a persistence store, and getting objects into a persistence store, is being abstracted by the use of repositories.
As you might have seen in the previous articles of this serie, I've already created 'dummy' repositories for the unit-tests.
Now, it is time to implement the 'real' repositories, which will actually do the work of loading / storing objects to our database.
In the 2nd part of this serie, I've already mentionned the existence of the DomainSettings class and the RepositoryFactory interface.
At that point, I've only implemented the 'mock-repositories', but now, I want to implement repositories which use NHibernate to do some real work. This means that I'll have to create an NHibernateRepositoryFactory class. I choose to put this class, along with the NHibernate-repositories in the same project / assembly where my business classes reside.
The NHibernateRepositoryFactory class must implement the IRepositoryFactory interface, which looks like this:

public interface IRepositoryFactory
{
ICustomerRepository CreateCustomerRepository();
IOrderRespository CreateOrderRepository();
...
}

There's one caveat here however... When using databases you'll be faced with 'Transactions'. A repository should not be the initiator nor the 'committer' of a transaction.
Why? The repository has no knowledge of the 'context' of the situation. The repository does not know when it should initiate and commit or rollback a unit-of-work.
As I've told earlier in this article, the NHibernate Session object is the NHibernate object which 'controls' a unit-of-work. Therefore, I'd like to extent the IRepositoryFactory interface with methods which allow me to create a specific repository with an object which is responsible for transaction-handling injected into it:

public interface IRepositoryFactory
{
ICustomerRepository CreateCustomerRepository();
IOrderRespository CreateOrderRepository();
...

ICustomerRepository CreateCustomerRepository( object transHandler );
IOrderRepository CreateOrderRepository( object transHandler );
}
This allows me to create repositories which can take part in a specific transaction/unit-of-work, and it also allows me to create repositories without having to take care about transactions. (This is also necessary; as you can see in the code in the Customer class in part 2 of this serie. There I need to retrieve a value, which is given to me by a repository. In this case, I do not really need a transaction context).

I've chosen to define the transHandler in my CreateXXX methods in the IRepositoryFactory as an object, since I do not want to couple the IRepositoryFactory interface with NHibernate.

At this time, I can already start writing an implementation of a NHibernateRepositoryFactory:

public class NHibernateRepositoryFactory :
IRepositoryFactory
{
public IOrderRepository CreateOrderRepository()
{
ISession s = DomainSettings.Instance.SessionFactoryObj.OpenSession();
return new NHibernateOrderRepository(s);
}

public IOrderRepository CreateOrderRepository( object transHandler )
{
// convert the transHandler to an NHibernat ISession object.
ISession s = transHandler as ISession;

if( s == null )
{
throw new ArgumentException ("object of type NHibernate.ISession expected.",
"transHandler");
}

return new NHibernateOrderRepository (s);
}
}
The NHibernateOrderRepository can look like this:
public class NHibernateOrderRepository :
IOrderRepository
{
private ISession _context;

public NHibernateOrderRepository( ISession s )
{
_context = s;
}

public Order GetOrder( int id )
{
return _context.Get (typeof(Order), id) as Order;
}

public decimal GetOrderTotalForCustomerSinceDate( Customer c, DateTime date )
{
string hql = "select sum (ol.NumberOfItems * ol.ArticlePrice) " +
"from Order o, " +
"OrderLine ol, Customer c " +
"where ol.OwningOrder = o and o.OwningCustomer = c " +
" and c.Id = :custId and o.OrderDate >= :orderDate";

IQuery q = _context.CreateQuery (hql);
q.SetInt32 ("custId", c.Id);
q.SetDateTime ("orderDate", date);

object o = q.UniqueResult ();

if( o == null || o == DBNull.Value )
{
return 0;
}
else
{
return Convert.ToDecimal (o);
}
}
}
I will not elaborate here on the HQL and the specific ISession methods which I've used in the code above, since this would be truly outside the scope of this article. For more information, I'd refer -again- to the Hibernate documentation or the Hibernate in Action book.
I do like to mention though that the bug which I've mentionned here is fixed in NHibernate 1.2.0 CR1. :)


As I'm typing this, I now also see that it would be better to let the repositories implement the IDisposable interface. In the Dispose method. In the Dispose method of the NHibernateRepositories, I can then check if my _context is still open, and close it if it is.
Then, I should also change the code in the Status property of the Customer class, so that it looks like this:

public CustomerStatus Status
{
get
{
CustomerStatus result = CustomerStatus.Normal;

using( IOrderRepository or =
DomainSettings.Instance.
RepositoryFactoryObj.
CreateOrderRepository () )
{
decimal orderTotal = or.GetOrderTotalForCustomerSinceDate(this,
DateTime.Now.AddMonths (-3));

if( orderTotal > DomainSettings.GoldAmountTreshold )
{
result = CustomerStatus.Gold;
}

}
...
return result;
}
If I don't do this, the ISession which is used by the OrderRepository would be kept open.


Using NHibernate in the client application

Now that we've seen (albeit rather quickly) how we can use NHibernate, it is time to integrate it in the client application.
Because of the way NHibernate works when it has to save changed objects back to the DB, I'd like to use long living sessions.
When you retrieve an object from the database, NHibernate will keep this object in the Session. When you save the object back to the database, NHibernate will try to find the object in the ISession instance which is used to perform the save. If the instance is found, NHibernate will update the corresponding record. If the instance is not found, NHibernate will create a new record.
If you use a separate ISession to retrieve an object from the DB, and use another ISession to persist this object back to the DB, NHibernate will asume that it has to insert a new record.
Therefore, it is -imho- best to use the same ISession instance for retrieving and saving the same business object instance.
When you're using NHibernate in Windows applications, you can do this by using the 'long conversation' model.

In short, this means that you can keep your session open as long as the user is busy with a 'unit-of-work', but you can disconnect your session from the database when no database-access is needed for a while.

Although this article doesn't provide really in-depth information, I'd like to finish it here. This is yet another article which is way to long (maybe I should stop writing such long posts), but if you've gotten to here, please feel free to post any comments, critics, remarks, ...