The NHibernate FAQ

session.CreateQuery("from Answers a where a.Type = Useful").List();

Article series on NHibernate and Fluent NHibernate – Part 3

Today the third part of my series on NHibernate and Fluent NHibernate went live. It took a little bit longer due to work overload. You can read it here.

Summary

In part 3 of this article series about NHibernate and Fluent NHibernate I have discussed how to let Fluent NHibernate automatically map a domain model to a data model. We have realized that FNH provides a reasonable mapping out of the box by using default conventions. I have shown how one can implement user defined conventions which will influence how the mapping is defined on a very fine grained level. I have also shown that if we use a base class in our domain which implements common functionality we can instruct FNH to ignore this class and just map the “real” entities.

FNH with its auto mapping feature reduces the task of mapping a complex domain to an underlying data model to just a few keystrokes. And as is always true: less code results in less bugs and less maintenance overhead.

Published at

Article series on NHibernate and Fluent NHibernate – Part 2

Today the second part of my series on NHibernate and Fluent NHibernate went live. You can read it here.

Summary

In part 2 of the article series I have continued to implement the remaining part of the domain which I had introduced in the first part. I discuss the mapping of various forms of relations between different entities. For all mappings I have presented the code needed to verify the mappings.

In part 3 of the article series I’ll show how one can further refactor and improve the mapping of the domain model. I’ll then discuss the usage of conventions and finally show how one can use the auto-mapping capabilities of Fluent NHibernate to completely avoid the explicit mapping of entities.

Published at

Article series on NHibernate and Fluent NHibernate

Sorry for having been quiet such a long time. But I was really busy lately. I wrote several articles for journals and other non NHibernate related posts. But now the good news for all of you who like my tutorial like posts...

I have been invited to write a series of articles on NHibernate and Fluent NHibernate on http://dotnetslackers.com.

The first part of this series has just been published. I invite you to read it here.

In this series I start from grounds up and will explain to the readers how easy it has become to write an NHibernate based application since Fluent NHibernate is available. I’ll explain the explicit mapping with the fluent syntax as well as the auto-mapping that Fluent NH offers.

This is a total overhaul compared to my first introduction to NHibernate of last year which is still the most popular post of this blog... ;-)

Enjoy.

Published at

Originally posted at

From a data centric to a domain driven design

Introduction

Is NHibernate as an ORM tool or framework better suited for a data centric application or for an application developed by applying domain driven design? Well, that should NOT be the question here. NHibernate can serve equally well both approaches. But which one would you choose?

A data centric design

The modeling of the data structure is the center piece of this kind of design. The database is the most important part of our architecture. The DBA plays a very important role.

Data Layer

That's ok for simple problems like managing a collection of customer addresses and nothing more. But it miserably fails as soon as we get into more complicated business. Let's e.g. assume that all of the sudden our address management tool needs to be extended to a full fledged CRM solution.

Possible Problems

  • Management night mare with possibly hundreds of stored procedures
  • No clear structure in the data. It seems that each entity (or table) has more or less the same importance
  • We concentrate to much on the data and not on the business processes and/or functionality

Our principle questions are focused around

  • Do we have all data that we need (tables and columns there in)?
  • Did we normalize the data sufficiently?

Instead of

  • What do we want to automate and why do we want to do so?
  • How can we measure that we have achieved what we want (criterions!)?

User Interface

On the other hand we concentrate too much on e.g. data binding on the GUI and how to best present (too much) data on the screen for the user.

A sample taken from a real application

This is a sample from a real application (although simplified). At the beginning there was a data model (ERD) which was elaborate by two persons in a "heroic" several men month long effort. Let's show an extract of this data model

image

It might be clear after staring a while on the ERD that we want to manage employees and their assigned tasks. It's also clear that an employee is a person and that it has an address and two different titles. Further on each employee can have an associated photo. Finally we see that the data regarding an employee is split into two different tables [Employee] and [EmployeeDetails] obviously for scalability reasons. Since photos can become very large (compared to the rest of the data) they are kept in a separate table [EmployeePhoto] which possibly resides in separate database file on another disk.

Stored Procedures

Traditionally Microsoft has suggested us to write stored procedures to access and manipulate the data in the various tables. So usually one would write the following kind of stored procedures for each table (here as an example we use the Address table)

  • usp_AddressInsert(...)
  • usp_AddressUpdate(...)
  • usp_AddressDelet(...)
  • usp_AddressSelectById(...)

if we look at a table like [Employee] we would probably have many more stored procedures representing various querying scenarios, e.g.

  • usp_EmployeeSelectAll()
  • usp_EmployeeSelectActive()
  • usp_EmployeeSelectByDepartment(...)
  • etc.

Data access objects (DAO)

Now having the stored procedures in place we write a DAO for each table to produce a object oriented wrapper around the database (the business object should not know anything about the database). We thus will have the following class for e.g. the Address table

public class AddressDAO
{
    public void Insert(...) {...}
    public void Update(...) {...}
    public void Delete(...) {...}
    public Address GetById(...) {...}
}

A domain driven design

The modeling of the business processes is the center piece of this kind of design. The so called domain model is the center of our architecture. The domain expert (a representative of the customer with deep knowledge of the domain for which the application is planned) plays a very important role during all the development phases (analysis, design and implementation). The development often is more evolutionary and goes in "cycles". It's often a so called agile application development.

Distilling the ubiquitous language

Together with the domain expert  we want to find and use the ubiquitous language which describes best the business we are talking of. In our simple case this ubiquitous language is "hidden" in the following fragments of a discussion

"... So we want to keep track of our employees. Especially we want to know where the employee lives and how we can contact him at home as well as in the office. To better identify an employee (and for other usage as well, e.g. to apply for a business travel visa) we want to have a photo of him in the system. ..."

"... yeah, each employee has a business card of course where he's title and job description is marked... thus I guess we have to store this information - we call it title - in the system as well since the relevant text for a new business card shall be generated automatically... By the way, the titles should be available in German and in English. ..."

"... each employee has a list of tasks to carry out during his daily work. This list should be maintained and updated by the system. Tasks can be produced automatically by the fact that some event occurred, e.g. there is a redemption of a bond. Other tasks are a result of a contact with a customer. And last but not least the group manager can define some tasks for an employee or a group of employees. ..."

"... as an employee I want to see a list of my open tasks. I want to also see if tasks are over due and which tasks will occur in the near future. ... I also want to see the priority of each task and what it's current status is. ..."

I have marked in bold the key terms for our simplified domain. These nouns will be good candidates for entities or value objects.

A first model of our domain

We can immediately locate two hot candidates for entities. These are employee and task. We also immediately grasp that a employee might have a list of associated tasks. Every thing else is just detail for the moment. So let's draw a nice diagram

image

Refining the model

Up to now our model does not contain much structure and business logic. Let's start with the question how we could better model the employee entity. At the moment the employee contains just a bunch of properties and no clear internal structure is visible. To find out e.g. whether an instance of employee is in a valid state is rather cumbersome. Comes the value object to the rescue! What about this?

image

In the above model I have tried to group properties which belong together. Let's take as an example the address. A valid address is represented by an address line, a postal code and a city (in the real world we would also have a link to a country there). An address line alone does not really make sense. Again: we can validate an address only if we have the whole group of relevant properties at hand. On the other hand it does not really make sense to put the address validation logic into the employee entity itself. Thus the extraction of a new class - the address class - is certainly an improvement. In the terminology of DDD the address is now a value object. It has no identity by itself and belongs to and characterizes an entity (the employee). A value object can be recreated any time by just copying the content of its properties. Further on a value object is immutable. Once created it cannot be changed. Two instances of a value object are equal if the content of their fields match. A value object can never be in an invalid state.

Let's have a look at the code of the address class then

public class Address : IEquatable<Address>
{
    public Address(string addressLine1, string addressLine2, string postalCode, string city)
    {
        if(addressLine1==null) 
            throw new ArgumentException("Address line 1 cannot be undefined.");
        if(postalCode==null) 
            throw new ArgumentException("Postal code cannot be undefined.");
        if(city==null) 
            throw new ArgumentException("City cannot be undefined.");
 
        AddressLine1 = addressLine1;
        AddressLine2 = addressLine2;
        PostalCode = postalCode;
        City = city;
    }
 
    public string AddressLine1 { get; private set; }
    public string AddressLine2 { get; private set; }
    public string PostalCode { get; private set; }
    public string City { get; private set; }
 
    public bool Equals(Address other)
    {
        if(other==null) return false;
        return AddressLine1 == other.AddressLine1 &&
               ((AddressLine2==null && other.AddressLine2==null) || 
               (AddressLine2 != null && AddressLine2 == other.AddressLine2)) &&
               PostalCode == other.PostalCode &&
               City == other.City;
    }
 
    public override bool Equals(object obj)
    {
        return Equals(obj as Address);
    }
 
    public override int GetHashCode()
    {
        return string.Format("{0}|{1}|{2}|{3}", 
            AddressLine1, AddressLine2, PostalCode, City).GetHashCode();
    }
}

Note that all properties are read-only to account for the fact that a value object is immutable. Thus an address can only be constructed through its constructor. Note also that I have implemented the interface IEquatable<T> and overridden the two methods Equals and GetHashCode to be able to compare two instances of type Address for equality. Pay attention on the special treatment of the AddressLine2 property in the Equal method. It's the only property that can be null. All others properties cannot be null. This requirement is enforced in the constructor where I check each non-nullable parameter and throw an exception if the requirement is not met.

The above code is a typical sample of how one would implement a value object.

I think it makes sense that also the Employee entity is always in a valid state. A possible solution how to achieve that is to also make all properties of the entity read-only and force any modification to use dedicated methods. I would also provide a constructor which expects all mandatory values, e.g.

public Employee(Name name, Title title1, Address homeAddress, Address officeAddress, 
    Contact homeContact, Contact officeContact)
{
    if (name == null)
        throw new ArgumentException("Name of employee cannot be undefined.");
    if (title1 == null)
        throw new ArgumentException("Title 1 of employee cannot be undefined.");
    if (homeAddress == null)
        throw new ArgumentException("Home address of employee cannot be undefined.");
    if (officeAddress == null)
        throw new ArgumentException("Office address of employee cannot be undefined.");
    if (homeContact == null)
        throw new ArgumentException("Home contact of employee cannot be undefined.");
    if (officeContact == null)
        throw new ArgumentException("Office contact of employee cannot be undefined.");
 
    Name = name;
    Title1 = title1;
    HomeAddress = homeAddress;
    OfficeAddress = officeAddress;
    HomeContact = homeContact;
    OfficeContact = officeContact;
}

Once an employee exists in the system and I want to e.g. change its home address then I use a dedicated method of the employee class

public void ChangeHomeAddress(Address newHomeAddress)
{
    if (newHomeAddress == null)
        throw new ArgumentException("Cannot change home address of employee to undefined.");
    HomeAddress = newHomeAddress;
}

This method again asserts that after the updating the employee instance is again in a valid state.

Summary

For me it's obvious that the domain driven approach is definitely the better way to go when implementing an application which models complex business processes. A more data centric approach may still make sense when dealing with a forms-over-data type application which does not involve complex business processes. But even when implementing a data centric application I would certainly never ever use stored procedures to access the data. I would instead use an ORM tool like NHibernate to access the database. The only exception I can see for justifying the use of stored procedures is in reporting scenarios where some massive data mapping, filtering and/or aggregation might be needed which is best done directly on the database server (in-process for maximum speed).

Enjoy

Blog Signature Gabriel

Published at

I'm a "Los Techies" member now

I just wanted to inform you that I have been invited to be a member of Los Techies which is a big honor for me.

LosTechies Logo

If you like my posts then you might as well have a look at my blog at LosTechies.  There I'll publish posts that do not necessarily have anything to do with NHibernate. To start with I have posted an article about the single responsibility principle (SRP) which I personally consider to be one of the most important principles for my daily development!

Don't be afraid, I'll continue to publish NHibernate related articles in this blog. So keep tuned.

Blog Signature Gabriel

Published at

Type analyzer - Interesting findings

When reading this post from Ayende I was getting curious what this site would tell about my blogging style here. The result is amusing me a lot.

INTJ - The Scientists

The long-range thinking and individualistic type. They are especially good at looking at almost anything and figuring out a way of improving it - often with a highly creative and imaginative touch. They are intellectually curious and daring, but might be physically hesitant to try new things.
The Scientists enjoy theoretical work that allows them to use their strong minds and bold creativity. Since they tend to be so abstract and theoretical in their communication they often have a problem communicating their visions to other people and need to learn patience and use concrete examples. Since they are extremely good at concentrating they often have no trouble working alone.

I would be very pleased if you could provide some feedback about what you are thinking of this findings... Especially interesting is the question whether

  • I am too abstract or theoretical
  • I can communicate my visions to you
  • My examples are concrete enough

Published at

Linq to NHibernate

The popularity of NHibernate is steadily increasing. At the same time people get used to LINQ. Now there exists a LINQ to NHibernate provider since quite some time. It's not a complete implementation of a LINQ provider but it is still quite useful. Most of the day to day problems we face when developing typical business application can be solved by using this provider. And if there is a query that cannot be executed against the provider we still have the option to falling back to the hibernate query language (HQL).

In this post I'll give you an introduction on how you can use NHibernate in conjunction with LINQ. Let's start with the definition of a domain model we are going to use when querying the database by using LINQ expressions or LINQ query operators.

The domain model

I have the following simple domain model. A person can have a set of assigned tasks.

model

The entities

I want to keep the entities as simple as possible for this example. So their implementation is as follows

public class Person
{
    public Person()
    {
        Tasks = new List<Task>();
    }
 
    public virtual long Id { get; set; }
    public virtual string Lastname { get; set; }
    public virtual string Firstname { get; set; }
    public virtual IList<Task> Tasks { get; set; }
}
 
public class Task
{
    public virtual long Id { get; set; }
    public virtual string TaskName { get; set; }
    public virtual DateTime DueDate { get; set; }
}

one thing worth noting is the fact that I instantiate a new empty Tasks collection in the constructor of the Person class.

The mapping

For the mapping of my domain model I am going to use the Fluent NHibernate framework (please refer to my previous posts for a detailed introduction to this framework: part 1, part 2, part 3, part 4) .

The Task is very easy to map

public class TaskMap : ClassMap<Task>
{
    public TaskMap()
    {
        Id(x => x.Id);
        Map(x => x.TaskName);
        Map(x => x.DueDate);
    }
}

And the person is nothing more complicated

public class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        Id(x => x.Id);
        Map(x => x.Firstname);
        Map(x => x.Lastname);
        HasMany<Task>(x => x.Tasks)
            .LazyLoad()
            .Cascade.All();
    }
}

Just let's have a look at the mapping of the Tasks collection. I want the tasks to only be lazy loaded when loading a person entity (LazyLoad). And I want NHibernate to automatically save or update any tasks associated with a given person if ever the person is updated (Cascade.All).

Test the mapping

One quick test I want to always do is to check whether my mappings work as expected. Since I use Fluent NHibernate this is very easy and straight forward. A lot of infrastructure code is available to me to leverage and thus simplify my unit test regarding mapping of the domain entities.

The base test fixture

First I want to present my base class I use for all of my tests. Every test fixture used in this post will inherit from this base class.

public class FixtureBase<TModel> where TModel : PersistenceModel, new()
{
    protected SessionSource SessionSource { get; set; }
    protected ISession Session { get; private set; }
 
    [SetUp]
    public void SetupContext()
    {
        var cfg = new SQLiteConfiguration()
                        .InMemory()
                        .ShowSql();
        SessionSource = new SessionSource(cfg.ToProperties(), new TModel());
        Session = SessionSource.CreateSession();
        SessionSource.BuildSchema(Session);
        
        Context();
        Because();
 
        Session.Flush();
        Session.Clear();
    }
 
    [TearDown]
    public void TearDown()
    {
        TearDownContext();
 
        Session.Close();
        Session.Dispose();
    }
 
    protected virtual void Context()
    {
    }
 
    protected virtual void Because()
    {
    }
 
    protected virtual void TearDownContext()
    {
    }
}

First of all my base fixture has a generic parameter TModel. TModel represents the persistence model used during the tests. The persistence model must inherit from the PersistenceModel (provided by Fluent NHibernate) and it must have a default constructor.

In the SetupContext method (which is executed before each test)

  • I define my configuration I want to use. Most of the time I use the SQLite database in in-memory mode for my database related tests. Fluent NHibernate provides me such a configuration object. For debugging purposes I declare that I want to see the SQL statements generated by NHibernate (ShowSql).
  • Second I create a session source and pass the above configuration as well as an instance of the model used to the constructor of the session source.
  • Then I create a new session object. Note that since I am using SQLite in in-memory mode I have to use the same session object during the whole test (including setup and tear down) since the database schema (and the data) is destroyed when the session is closed.
  • I now use the Session object created above to generate the database schema. The schema is generated from the information provided by the model (which consists of all mappings)
  • Now I call the virtual Context and Because methods. The reason is that I want my unit test to be more BDD like
  • Finally I flush all pending operations from the session to the database and then clear the session.

The persistence model

The persistence model I am using is very straight forward. I just include all class mappings that are in the same assembly as the PersonMap.

public class TestModel : PersistenceModel
{
    public TestModel()
    {
        addMappingsFromAssembly(typeof(PersonMap).Assembly);
    }
}

I could also explicitly add mappings if I want so

public class TestModel : PersistenceModel
{
    public TestModel()
    {
        addMapping(new PersonMap());
        addMapping(new TaskMap());
    }
}

The test

Writing a test for the mapping is really straight forward with the aid of the PersistenceSpecification class provided by Fluent NH.

[Test]
public void can_add_person_without_tasks()
{
    new PersistenceSpecification<Person>(Session)
        .CheckProperty(x => x.Firstname, "Gabriel")
        .CheckProperty(x => x.Lastname, "Schenker")
        .VerifyTheMappings();
}

or a test which also tries to add tasks

[Test]
public void can_add_person_with_tasks()
{
    var tasks = new[]
                    {
                        new Task {TaskName = "Task 1", DueDate = DateTime.Today.AddDays(5)},
                        new Task {TaskName = "Task 2", DueDate = DateTime.Today.AddDays(6)},
                        new Task {TaskName = "Task 3", DueDate = DateTime.Today.AddDays(3)},
                    };
    new PersistenceSpecification<Person>(Session)
        .CheckProperty(x => x.Firstname, "Gabriel")
        .CheckProperty(x => x.Lastname, "Schenker")
        .CheckList(x=>x.Tasks, tasks)
        .VerifyTheMappings();
}

Do I need to tell that the tests pass successfully? It's really that easy... I have not needed a single line of XML so far. And no "magic strings" are involved. For me it's really a joy to work like this.

And now finally we get LINQ into the play

The context

In LINQ the notion of a context is very important. It represent kind of a facade to the database. LINQ to NHibernate provides us a base class from which we can derive when we define our own context. In our simplified model we have only 2 entities and thus our context needs just two members to have access via LINQ to either the persons or tasks.

public class SampleContext : NHibernateContext
{
    public SampleContext(ISession session)
        : base(session)
    { }
 
    public IOrderedQueryable<Person> Persons
    {
        get { return Session.Linq<Person>(); }
    }
 
    public IOrderedQueryable<Task> Tasks
    {
        get { return Session.Linq<Task>(); }
    }
}

Testing

Now I want to implement a first test to check whether LINQ to NHibernate does indeed work as expected. First I have to setup a context where I have some person object with tasks in the database

public class a_repository_with_persons_having_tasks : Person_Fixture
{
    protected Person[] persons;
    private IList<Task> tasks1, tasks2, tasks3;
 
    protected override void Context()
    {
        base.Context();
        tasks1 = new[]
                     {
                         new Task {TaskName = "Task 1.1", DueDate = DateTime.Today.AddDays(5)},
                         new Task {TaskName = "Task 1.2", DueDate = DateTime.Today.AddDays(6)},
                         new Task {TaskName = "Task 1.3", DueDate = DateTime.Today.AddDays(3)},
                     };
        tasks2 = new[]
                     {
                         new Task {TaskName = "Task 2.1", DueDate = DateTime.Today.AddDays(5)},
                         new Task {TaskName = "Task 2.2", DueDate = DateTime.Today.AddDays(6)},
                         new Task {TaskName = "Task 2.3", DueDate = DateTime.Today.AddDays(3)},
                     };
        tasks3 = new[]
                     {
                         new Task {TaskName = "Task 3.1", DueDate = DateTime.Today.AddDays(5)},
                         new Task {TaskName = "Task 3.2", DueDate = DateTime.Today.AddDays(6)},
                         new Task {TaskName = "Task 3.3", DueDate = DateTime.Today.AddDays(2)},
                     };
        persons = new[]
                      {
                          new Person {Firstname = "Gabriel", Lastname = "Schenker", Tasks = tasks1},
                          new Person {Firstname = "John", Lastname = "Doe", Tasks = tasks2},
                          new Person {Firstname = "Ann", Lastname = "Moe", Tasks = tasks3},
                      };
        foreach (var person in persons)
            Session.Save(person);
    }
}

Now I can write a test for the case where I want to retrieve all persons from the database

[TestFixture]
public class when_querying_all_persons : a_repository_with_persons_having_tasks
{
    private IEnumerable<Person> list;
 
    protected override void Because()
    {
        list = from p in db.Persons
               select p;
    }
 
    [Test]
    public void should_return_all_persons()
    {
        list.Count().ShouldEqual(persons.Length);
    }
}

The query generated by the above test is

SELECT  this_.Id as Id0_0_, 
        this_.Lastname as Lastname0_0_, 
        this_.Firstname as Firstname0_0_ 
FROM [Person] this_

That's exactly what we were expecting!

Using Where to get a filtered list

Now let's do some more interesting stuff. I want to have a filtered list of persons

[TestFixture]
public class when_retrieving_filtered_list_of_persons : a_repository_with_persons_having_tasks
{
    [Test]
    public void can_filter_by_LastName()
    {
        var list = db.Persons.Where(x=>x.Lastname=="Doe");
        list.Count().ShouldEqual(1);
    }
 
    [Test]
    public void can_filter_by_task()
    {
        var list = from p in db.Persons
                   from t in p.Tasks
                   where t.DueDate == DateTime.Today.AddDays(3)
                   select p;
        list.Count().ShouldEqual(2);
    }
}

In the first test I use the Where extension method defined by LINQ to filter my collection of persons. The extension methods defined by LINQ are also called query operators. The select statement generated by Linq2NH is

SELECT count(*) as y0_ 
FROM [Person] this_ 
WHERE this_.Lastname = @p0; 
@p0 = 'Doe'

In the second test I use the new language extension introduced for C# (also called a query expression) to get a filtered set of persons. This time we get the following select statement sent to the database

SELECT          count(*) as y0_ 
FROM            [Person] this_ 
left outer join [Task] t1_ on this_.Id=t1_.Person_id 
WHERE t1_.DueDate = @p0; 
@p0 = '29.11.2008 00:00:00'

Obviously also joins between tables work as expected.

Getting ordered lists

Often we need an ordered list of items, in this case persons ordered by their last name.

[Test]
public void can_order_by_LastName()
{
    var list = db.Persons.OrderBy(x => x.Lastname);
    list.First().Lastname.ShouldEqual("Doe");
}

The query generated is

SELECT  this_.Id as Id0_0_, 
        this_.Lastname as Lastname0_0_, 
        this_.Firstname as Firstname0_0_ 
FROM [Person] this_ 
ORDER BY this_.Lastname asc

Code

The code accompanying this post can be found here.

Summary

It is straight forward to use LINQ to NHibernate. Although the Linq2NH provider is not fully implemented it is more than sufficient for most scenarios we encounter in typical projects. And if ever we encounter a query that cannot be executed through the Linq2NH provider we can still implement the query by using HQL instead.

GabrielEnjoy

 Blog Signature Gabriel

Published at

Legacy DB and one-to-one relations

When dealing with a legacy database one often encounters the situation that the database schema defines one-to-one relations between two entities. A typical example might be the following schema fragment

erd

with a one-to-one relation between person and address, that is: each person can have an address and an address can only belong to a single person. To guarantee that a single person can only have zero or one address the foreign key column PersonId in the Address table is set to be unique.

Such a construct is not straight forward to map in NHibernate! I want to show you one possible solution. The solution works but is not free from certain hick-ups! Let's first model the domain

The domain model

model

the code for the above model is straight forward. Nothing magic

public class Person
{
    public virtual int Id { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual Address Address { get; private set; }
 
    public virtual void AssignAddress(Address address)
    {
        Address = address;
        address.Owner = this;
    }
}
 
public class Address
{
    public virtual int Id { get; set; }
    public virtual string AddressLine1 { get; set; }
    public virtual string AddressLine2 { get; set; }
    public virtual string PostalCode { get; set; }
    public virtual string City { get; set; }
    public virtual Person Owner { get; set; }
}

Note that I have defined the setter method of the Address property in the Person entity as private such as that the consumer of the code is forced to use the AssignAddress method which sets up the bi-directional relation.

The mapping

And now we try to find a working mapping. I use the Fluent NHibernate framework for the mapping (please refer to my previous posts for an introduction to this framework: part 1, part 2, part 3, part 4)

public class PersonMapper : ClassMap<Person>
{
    public PersonMapper()
    {
        LazyLoad();
 
        Id(x => x.Id);
        Map(x => x.FirstName);
        Map(x => x.LastName);
        HasOne(x => x.Address)
            .PropertyRef(p => p.Owner)
            .Cascade.All()
            .FetchType.Join();
    }
}
 
public class AddressMapper : ClassMap<Address>
{
    public AddressMapper()
    {
        LazyLoad();
 
        Id(x => x.Id);
        Map(x => x.AddressLine1);
        Map(x => x.AddressLine2);
        Map(x => x.PostalCode);
        Map(x => x.City);
        References(x => x.Owner)
            .WithUniqueConstraint()
            .TheColumnNameIs("PersonId")
            .LazyLoad()
            .Cascade.None();
    }
}

Unit Tests

What does the above mapping derive as database schema? Let's implement a test. First I have to define what is my model (or: where are my mappings to be found)

public class TestModel : PersistenceModel
{
    public TestModel()
    {
        addMappingsFromAssembly(typeof(Person).Assembly);
    }
}

I then use the following code to generate the schema

[TestFixture]
public class when_creating_the_schema 
{
    [SetUp]
    protected void Context()
    {
        var model = new TestModel();
        var config = new Configuration();
        config.Configure();
        model.Configure(config);
        var factory = config.BuildSessionFactory();
        var session = factory.OpenSession();
        new SchemaExport(config).Execute(true, false, false, false, session.Connection, null);
    }
 
    [Test]
    public void smoke_test()
    {
        true.ShouldBeTrue();
    }
}

when using an SQLite database (in-memory mode) the output generated by the smoke test is

unittestschema

let me reformat the create table scripts a little bit

create table [Person] (
  Id  integer, 
  LastName TEXT, 
  FirstName TEXT, 
  primary key (Id))
  
create table [Address] (
  Id  integer, 
  AddressLine1 TEXT, 
  AddressLine2 TEXT, 
  PostalCode TEXT, 
  City TEXT, 
  PersonId INTEGER unique, 
  primary key (Id))

we can clearly see that the schema created from the model is indeed equal to the schema in the legacy database. Especially note that the PersonId foreign key in the Address table is set to be unique. Now that is a good start...!

Let's see how the creation of a new person with an associated address works (if ever). I have implemented the following unit test

[TestFixture]
public class when_adding_a_new_person_with_an_address : Person_Fixture
{
    private Address address;
    private Person person;
 
    protected override void Context()
    {
        base.Context();
        address = new Address
                      {
                          AddressLine1 = "Some Street 1",
                          PostalCode = "8000",
                          City = "Zurich"
                      };
        person = new Person {FirstName = "Gabriel", LastName = "Schenker"};
        person.AssignAddress(address);
        Session.Save(person);
        Session.Flush();
        Session.Clear();
    }
 
    [Test]
    public void smoke_test()
    {
        true.ShouldBeTrue();
    }
}

in the context I create a new person entity and assign it a new address. Then I save the person, flush and clear the session. The smoke test just verifies that the context can be set up without throwing an exception. Let's run the test and analyze the output

createpersontest

and indeed this works as expected. First a person record is created and the the associated address is created.

Now let's have a look what happens when we query for this person. I add this test to the above test class

[Test]
public void should_add_person_to_database()
{
    var fromDb = Session.Get<Person>(person.Id);
    fromDb.ShouldNotBeNull();
    fromDb.ShouldNotBeTheSameAs(person);
    fromDb.LastName.ShouldEqual(person.LastName);
    fromDb.FirstName.ShouldEqual(person.FirstName);
}

In the first line I load the person entity which I have previously created from database. I then assert that the entity does indeed exist and has the expected properties. The following test output is generated

queryperson

The interesting part is the one outlined by the red rectangle. When I load a person two select statements are generated. One to load the person record and the second to load its associated address.

Problems with this implementation

When loading a single person entity this is no problem but it starts to be a problem when I try to load a list of persons, as I do in the following test

public void can_load_all_persons()
{
    var list = Session.CreateQuery("from Person").List<Person>();
}

the output generated is

querylistofpersons

In this test I have 3 persons (each having an address) in the database. The problem is that although only one select statement is generated for the Person table there are 3 select statements for loading the corresponding addresses. We have a typical select (n+1) problem which is BAD.

A possible solution to avoid the select n+1 problem

A possible solution to this problem is shown below

[Test]
public void can_load_all_persons_revisited()
{
    var list = Session.CreateQuery("select p.Id, p.LastName from Person p").List();
}

here I explicitly select the fields I want to retrieve from database. And indeed the result of the test is only one select statement

querylistofpersons 2

We can use this method when we need a lookup list with all or some persons in the database.

Code

The code accompanying this post can be found here.

Summary

I have shown a possible solution how one can map a one-to-one relation implied by a pre-existing legacy database with NHibernate. For the mapping I have used the Fluent NHibernate framework. There is a select (n+1) problem with this implementation. But this problem can be avoided by using customized queries.

Enjoy.

Blog Signature Gabriel

Published at

Lazy loading BLOBS and the like in NHibernate

[Updated, 2008-11-20 --> see end of post]

One of the questions that is asked again and again in the NHibernate user mailing list is the question about whether NHibernate supports lazy-loading of properties. The answer is NO - at least for the time being. Why is this question reasonable? Well, often we have entities in our domain that contain fields with large amount of data. Some samples are

  • a large binary object (BLOB, e.g. an image, a Word document, a PDF, etc.),
  • a large text object (CLOB, or nvarchar(max) )
  • a cluster of rarely used extra fields

The problem is that we do not always need all this information when loading an entity. Thus we can massively improve the performance of our queries if those fields would only be loaded on demand.

The Model

Let's have a look at the following simplified domain model.

model

Here the person entity has an associated photo. The photo has been extracted from the person entity since NHibernate does not support lazy load of specific properties of an entity (as mentioned above) and thus each time we load a person entity we would also load its photo which might be huge (e.g. several MB).

The code for the person entity is simple

public class Person
{
    public virtual Guid Id { get; private set; }
    public virtual string LastName { get; private set; }
    public virtual string FirstName { get; private set; }
    public virtual PersonPhoto Photo { get; private set; }
 
    // to satisfy NHibernate only!
    protected Person() { }
 
    public Person(string lastName, string firstName, PersonPhoto personPhoto)
    {
        LastName = lastName;
        FirstName = firstName;
        AssignPhoto(personPhoto);
    }
 
    public virtual void AssignPhoto(PersonPhoto photo)
    {
        Photo = photo;
        photo.Owner = this;
    }
}

please note that I have defined a method to assign a photo to the person. This method takes care of the fact that the relation between the person and the photo entity is bi-directional (via the assignment photo.Owner = this). I have omitted any validation code for brevity.

Let's also have a look at the implementation of the PersonPhoto class which I kept even simpler

public class PersonPhoto
{
    public virtual Guid Id { get; set; }
    public virtual Person Owner { get; set; }
    public virtual byte[] Image { get; set; }
}

Let's now define the mapping for my simple model.

Mapping with XML

The question is now: how can I map this model to achieve the desired result that is

  • whenever I load a person its photo is not automatically loaded but only on request (lazy load)
  • treating the person photo like an associated entity of the person entity, that is the photo is created, updated and deleted together with its parent - the person.

It is not possible in NHibernate to define a (bi-directional) one-to-one relation between Person and PersonPhoto and requesting at the same time that the PersonPhoto is lazy loaded.

But a possible solution to declare the relation between Person and PersonPhoto as many-to-one and between PersonPhoto and Photo as one-to-one.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="Blobs"
                   namespace="Blobs">
  <class name="Person">
    <id name="Id">
      <generator class="guid"/>
    </id>
    <property name="LastName"/>
    <property name="FirstName"/>
    <many-to-one name="Photo" class="PersonPhoto" unique="true"
                 column="PersonPhotoId" cascade="all-delete-orphan"/>
  </class>
  
  <class name="PersonPhoto">
    <id name="Id">
      <generator class="guid"/>
    </id>
    <property name="Image" type="BinaryBlob"/>
    <one-to-one name="Owner" property-ref="Photo" constrained="true"/>
  </class>
</hibernate-mapping>

It is important to note that the many-to-one relation defined in the Person mapping is declared as unique to avoid that a single photo is assigned to more than one person. Also I define that each insert, update and delete action applied to a person entity should be cascaded to the associated PersonPhoto entity.

Unit testing the XML mapping

Let's now write some unit tests that verify that my requirements are indeed satisfied.

[Updated]

First I want to analyze what database schema is created. Remember: whenever I have the possibility to start a so called green field project I always start by defining the domain and then let the database auto-generated from the domain (that is: the database is only an implementation detail). Things might be different if you have to use a pre-existing database though...

So my unit test to verify that the schema can indeed be created is

[TestFixture]
public class when_creating_the_schema : Person_Fixture
{
    protected override void Context()
    {
        base.Context();
        new SchemaExport(Configuration).Execute(true, false, false, false, Session.Connection, null);
    }
 
    [Test]
    public void smoke_test()
    {
        true.ShouldBeTrue();
    }
}

In the last line of the Context method I use the SchemaExport class of NHibernate to generate the database schema from the model and the mapping information. The first (and only) test I write is a so called smoke test, that is it's a dummy test which should run just to test that setting up the context doesn't throw an exception. And indeed the test succeeds and the following output is produced

DbSchemaGenerationTest

The script is generated for the SQLite database I use. For a different type of database server the script would look slightly different. The two tables created are

create table Person (
  Id UNIQUEIDENTIFIER not null, 
  LastName TEXT, 
  FirstName TEXT, 
  PersonPhotoId UNIQUEIDENTIFIER unique, 
  primary key (Id)
)
 
create table PersonPhoto (
  Id UNIQUEIDENTIFIER not null, 
  Image BLOB, 
  primary key (Id)
)

Second I want to test whether I can create a new person object having a photo and save this aggregate to the database.

[TestFixture]
public class when_adding_a_new_person_with_a_photo : Person_Fixture
{
    private PersonPhoto photo;
    private Person person;
 
    protected override void Context()
    {
        base.Context();
        photo = new PersonPhoto {Image = Encoding.Default.GetBytes("This is a placeholder for a photo...")};
        person = new Person("Schenker", "Gabriel", photo);
        Session.Save(person);
 
        // clean up
        Session.Flush();
        Session.Clear();
    }
}

In the above code I have setup the context, that is - I want to add a new person with photo to the database - (please have a look at the source code regarding the base class Person_Fixture which I use)

The first test I write is again smoke test, which should run just to test that setting up the context doesn't throw an exception.

// Smoke test
[Test]
public void should_execute_without_an_error()
{
    true.ShouldBeTrue();
}

And indeed, if you run this test it is green. This tells me that the method Context is running without causing an exception.

Remarks: All the ShouldXXX methods you'll see in the presented code fragments are extension methods I defined and use for better readability of the code. You can find them here.

The second test method checks whether there exists indeed a person record in the database

[Test]
public void person_should_exist_in_the_database()
{
    var fromDb = Session.Get<Person>(person.Id);
    fromDb.ShouldNotBeNull();
    fromDb.ShouldNotBeTheSameAs(person);
    fromDb.LastName.ShouldEqual(person.LastName);
    fromDb.FirstName.ShouldEqual(person.FirstName);
}

In the above code I first check whether a non null object is loaded from db and then whether it is a different instance (that is it has not been just loaded from the first level cache of NHibernate --> please see also this post) which means it has really been loaded from the database. Finally I check some of the properties for equality. As you might have expected: this test is green when run.

Now I want to also check whether the photo has really been stored in the database or not. The following test should confirm that

[Test]
public void person_photo_should_exist_in_the_database()
{
    var fromDb = Session.Get<Person>(person.Id);
 
    fromDb.Photo.ShouldNotBeNull();
    fromDb.Photo.ShouldNotBeTheSameAs(person.Photo);
    fromDb.Photo.Image.ShouldEqual(person.Photo.Image);
}

Well, green again when run - so no problem!

One important thing to check is that the very same photo cannot assigned to two different person instances. Each photo is uniquely assigned to a certain person. The following test verifies that behavior.

[Test]
public void adding_another_person_with_same_photo_should_not_be_possible()
{
    var otherPerson = new Person("Doe", "John", photo);
    Session.Save(otherPerson);
    try
    {
        Session.Flush();
        Assert.Fail("Expected exception!");
    }
    catch(HibernateException)
    {
        Session.Clear();
    }
}

this code needs some further explanation. As you probably can see I expect that NHibernate throws an exception when trying to add a new person having the same photo as an already existing person. The exception is not thrown when calling the save method of the session but only when the session is flushed (that is: the insert command is executed on the database). I clear the session in the catch block since otherwise the exception would be raised again by my test tear-down method (in the base fixture class) which also flushes and disposes the session object.

The above test also passes and thus we are left with only one additional test. Does the person photo indeed lazy load? Let's write a test which verifies this

[TestFixture]
public class when_loading_an_existing_person_from_database : Person_Fixture
{
    private PersonPhoto photo;
    private Person person;
 
    protected override void Context()
    {
        base.Context();
        photo = new PersonPhoto { Image = Encoding.Default.GetBytes("This is a placeholder for a photo...") };
        person = new Person("Schenker", "Gabriel", photo);
        Session.Save(person);
 
        // clean up
        Session.Flush();
        Session.Clear();
    }
 
    [Test]
    public void Person_photo_should_be_lazy_loaded()
    {
        var fromDb = Session.Load<Person>(person.Id);
 
        NHibernateUtil.IsInitialized(fromDb.Photo).ShouldBeFalse();
 
        var image = fromDb.Photo.Image;
 
        NHibernateUtil.IsInitialized(fromDb.Photo.Image).ShouldBeTrue();
    }
}

Again I first setup the context for the test, that is I add a person with a photo to the database. Then in the test method I load the previously save person from database and with the aid of a utility class of NHibernate I check whether the property Photo of the person entity is un-initialized (i.e. the entity behind the property is not loaded). Then I access the property and finally I use the utility class again to test whether now the photo has been (lazy) loaded.

Wow - the test passes! We have found a mapping which satisfies all our needs!

Mapping with Fluent NHibernate

As described in earlier posts (part 1, part 2, part 3 and part 4) we have the possibility to use Fluent NHibernate to map our entities. Mapping this way has many advantages (I already discussed in the posts just mentioned). Let's have a look at the mapping needed for the Person entity

public class PersonMapper : ClassMap<Person>
{
    public PersonMapper()
    {
        LazyLoad();
        
        Id(x => x.Id);
        Map(x => x.FirstName);
        Map(x => x.LastName);
        References(x => x.Photo)
            .FetchType.Select()
            .Cascade.All()
            .TheColumnNameIs("PersonPhotoId")
            .WithUniqueConstraint();
    }
}

I define a mapper class which inherits form the generic ClassMap<T> base class provided by the Fluent NHibernate framework. In the constructor of this class I define the mapping. The first line defines that I want my person entity to be lazy loaded (by default in Fluent NHibernate all entities are NOT lazy loaded).

The many-to-one relation between person and person photo is mapped with the aid of the References method.

The PersonPhoto entity is mapped as follows

public class PersonPhotoMapper : ClassMap<PersonPhoto>
{
    public PersonPhotoMapper()
    {
        LazyLoad();
        Id(x => x.Id);
        Map(x => x.Image);
        HasOne(x => x.Owner)
            .PropertyRef(x=>x.Photo)
            .Constrained();
    }
}

Here the part that interests us most (the reverse relation from photo to person) is mapped with the aid of the HasOne method.

Unit testing the Fluent NHibernate mapping

There is not much to say about this. The unit test are nearly the same with only one difference. I use a different base class from which I derive all my test classes. The definition of the base class used can be found here.

Code

You can find the accompanying this post here.

Summary

I have shown you a way how you can structure your domain model and map your entities to be able to lazy load "extra" information of a given entity. I have explained how to map the domain by using standard XML mapping files as well as by using the Fluent NHibernate framework. By applying this technique you can massively improve the performance of queries and reduce the bandwidth needed to transfer data from the database to the consuming client.

[Update] Uni-directional link between Person and PersonPhoto

In a comment I was asked why I implemented the relation between the person and the person photo entity as bi-directional and whether it would not be possible to only implement and uni-directional realtion between person and person photo.

The answer is: there is NO special reason for having a bi-directional relation (Eric Evans in his DDD book even suggests to keep the relations uni-directional whenever possible). And yes, it is possible to implement the sample with an uni-directional relation. I'll show the details below (this time I only show the mapping in Fluent NHibernate but the XML mapping is straight forward.

Here is the model with only an uni-directional relation

unidirectional_model

and the code

public class Person
{
    public virtual Guid Id { get; private set; }
    public virtual string LastName { get; private set; }
    public virtual string FirstName { get; private set; }
    public virtual PersonPhoto Photo { get; private set; }
 
    // to satisfy NHibernate only!
    public Person() { }
 
    public Person(string lastName, string firstName, PersonPhoto personPhoto)
    {
        LastName = lastName;
        FirstName = firstName;
        AssignPhoto(personPhoto);
    }
 
    public virtual void AssignPhoto(PersonPhoto photo)
    {
        Photo = photo;
    }
}
 
public class PersonPhoto
{
    public virtual Guid Id { get; set; }
    public virtual byte[] Image { get; set; }
}

Now let me show the mapping for this model (Fluent NHibernate)

public class PersonMapper : ClassMap<Person>
{
    public PersonMapper()
    {
        LazyLoad();
        
        Id(x => x.Id);
        Map(x => x.FirstName);
        Map(x => x.LastName);
        References(x => x.Photo)
            .FetchType.Select()
            .Cascade.All()
            .TheColumnNameIs("PersonPhotoId")
            .WithUniqueConstraint();
    }
}
 
public class PersonPhotoMapper : ClassMap<PersonPhoto>
{
    public PersonPhotoMapper()
    {
        LazyLoad();
 
        Id(x => x.Id);
        Map(x => x.Image);
    }
}

If I generate the schema from this model I get the very same create table scripts as in the bi-directional sample. And all the other unit tests I have shown above run successfully.

The code has been updated to contain both samples the uni- and the bi-directional relation.

Enjoy

Blog Signature Gabriel

Published at

First and Second Level caching in NHibernate

I'll try to dive deep into the caching of NHibernate in this article. This post has been inspired by the talk given by Oren Eini (aka Ayende) at the Kaizen Conference in Austin TX.

Caching is a topic that is IMHO only superficially described so far especially regarding the second level cache. Most of the time one finds a lot of information about how to configure a specific cache provider for usage but the real usage (who and when) is not really described. I hope to be able to provide some of the missing pieces with this post.

The full source code used for this post can be found here.

First Level Cache

When using NHibernate the first level cache is automatically enabled as long as one uses the standard session object. We can avoid to use a cache at all when using the stateless session provided by NHibernate though. The stateless session is especially useful for reporting situations or for batch processing. When NHibernate is loading an entity by its unique id from the database then it is automatically put into the so called identity map. This identity map represents the first level cache.
The life-time of the first level cache is coupled to the current session. As soon as the current session is closed the content of the respective first level cache is cleared. Once an entity is in the first level cache a subsequent operation that wants to load the very same entity inside the current session retrieves this entity from the cache and no roundtrip to the database is needed.
One of the main reasons behind this entity map is to avoid the situation that two different instances in memory can represent the same database record (or entity). The NHibernate session object provides us two ways to retrieve an entity by its unique id from the database. There are subtle but important differences between them.

Let's implement an Account class for our samples

public class Account
{
    public virtual int Id { get; private set; }
    public virtual string Name { get; private set; }
    public virtual decimal Balance { get; private set; }
 
    protected Account()
    {
    }
 
    public Account(string name, decimal balance)
    {
        Name = name;
        Balance = balance;
    }
 
    public virtual void Credit(decimal amount)
    {
        Balance += amount;
    }
}

the corresponding XML mapping file is

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   namespace="Caching"
                   assembly="Caching">
  <class name="Account">
    <id name="Id">
      <generator class="hilo"/>
    </id>
    <property name="Name"/>
    <property name="Balance"/>
  </class>
</hibernate-mapping>

Get an entity from database

With the session.Get(id) method we can retrieve an entity from database. If there is no record found in the database with the given id then null is returned.
On the other hand if a record with the given unique id exists in the database then NHibernate loads this record and instantiates a fully populated entity in memory and immediately puts this entity into the entity map (or first level cache)
Assuming that a specific record has already been loaded from database inside the current session then a subsequent Get(id) operation will return the cached entity to the caller. We can see this in the following output produced by the unit test. There is only ONE select statement produced by NHibernate

FistLevelCache

The above output was produced by this unit test

[Test]
public void trying_to_get_the_same_account_a_second_time_should_get_the_account_from_1st_level_cache()
{
    Console.WriteLine("------ now getting entity for the first time");
    var acc1 = Session.Get<Account>(account.Id);
    Console.WriteLine("------ now getting entity for the second time");
    var acc2 = Session.Get<Account>(account.Id);
 
    acc1.ShouldBeTheSameAs(acc2);
}

Load an entity from database

When using the session.Load(id) method NHibernate only instantiates a proxy for the given entity. As long as we only access the id of the entity the entity itself is not loaded from the database. Only when we try to access one of the other properties of the entity NHibernate loads the entity from the database. We can see this clearly in the following output produced by the unit test. I have added some comment to the output to make it easier to verify the result.

Here is a unit test

[Test]
public void trying_to_load_a_non_existing_entity()
{
    var acc1 = Session.Load<Account>(account.Id);
    acc1.ShouldNotBeNull();
    Console.WriteLine("------ now accessing the id of the entity");
    Console.WriteLine("The id is equal to {0}", acc1.Id);
    acc1.Id.ShouldEqual(account.Id);
    Console.WriteLine("------ now accessing a property (other than the ID) of the entity");
    Console.WriteLine("The name of the account is: {0}", acc1.Name);
    acc1.Name.ShouldEqual(account.Name);
}

and the output produced by the above code

FistLevelCache2

Using Load to optimize data access

The behavior mentioned above is especially useful when creating or updating complex entities which have relations to other entities. Assume that the account entity references a customer entity and I want to create a new account for a customer from which I only know its unique id. Then my code might look as follows

var newAccount = new Account("EUR Account 1", 1250m);
newAccount.Customer = Session.Load<Customer>(customerId);
Session.Save(newAccount);

Note that I use the Load method to get the (existing) customer entity. NHibernate will not physically load the customer since in the account table on the database there is only the id of the customer needed (as a foreign key). And as I mentioned above, as long as you only use the id of an entity retrieved with the Load method the corresponding entity is not physically loaded from the database.

Second level cache

The life time of the second level cache is tied to the session factory and not to an individual session. Once an entity is loaded by its unique id and the second level cache is active the entity is available for all other sessions (of the same session factory). Thus once the entity is in the second level cache NHibernate won't load the entity from the database until it is removed from the cache.
To enable the second level cache we have to adjust our configuration file. We have to define which cache provider we want to use. There exist various implementations of a second level cache. For our sample we use a Hashtable based cache which is included in the core NHibernate assembly. Please note that you should never use this cache provider for production code but only for testing. Please refer to the chapter "Second Level Cache implementations" below to decide which implementation fits best for your needs. You won't have to change your code if you change the cache provider though.

We have to add the the following line to the configuration file

    <property name="cache.provider_class">NHibernate.Cache.HashtableCacheProvider</property>

this will instruct NHibernate to use the previously mentioned Hashtable based cache provider as a provider for the second level cache.
Now let's have a look at the following unit test.

[Test]
public void trying_to_load_an_existing_item_twice_in_different_sessions_should_use_2nd_level_cache()
{
    using(var session = SessionFactory.OpenSession())
    {
        var acc = session.Get<Account>(account.Id);
        acc.ShouldNotBeNull();
    }
 
    using(var session = SessionFactory.OpenSession())
    {
        var acc = session.Get<Account>(account.Id);
        acc.ShouldNotBeNull();
    }
}

In the above test we open a first session and load an existing entity from the database. Then we open a second session and try to load the very same entity from the database again. Without a second level cache we would expect that NHibernate loads the entity two times from the database since we are using 2 different sessions and thus the first level cache can not be used to avoid a roundtrip to the database. So let's have a look at the result produced.

SecondLevelCache

Wait a moment - we clearly see two select statements instead of only one. What did we do wrong? This is not an error, no but it's a feature. NHibernate does not enable the second level cache by default, since it would have too many undesired implications. One has to explicitly enable the second level cache. If we add the following statement to the configuration file

    <property name="cache.use_second_level_cache">true</property>

we activate the second level cache. But that is still not enough. We have to also enable our entity to be cached in the second level cache.
This can be done by adding the following statement to the entity's mapping file

    <cache usage="read-write"/>

If we now run the unit test again we obtain the expected result. The entity is loaded only once from the database. The second time it is loaded from the second level cache.
Now if we try to update an entity which is already in the second level cache then this entity should also be automatically updated in the second level cache. The following unit test should prove this behavior.

[Test]
public void when_updating_the_entity_then_2nd_level_cache_should_also_be_updated()
{
    using(var session = SessionFactory.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        var acc = session.Get<Account>(account.Id);
        acc.Credit(200m);
        tx.Commit();
    }
 
    using(var session = SessionFactory.OpenSession())
    {
        var acc = session.Get<Account>(account.Id);
        acc.Balance.ShouldEqual(1200m);
    }
}

and indeed it does as we can see in the test output. Again the entity is loaded from the cache the second time it is requested although it was updated (no select statement after the update statement). The last line in the test code verifies that the entity was indeed updated.
SecondLevelCache2 

Second Level Cache Providers

All second level cache providers are part of the NHibernate contribution. The following list gives as short description of each provider.

  • Velocity: uses Microsoft Velocity which is a highly scalable in-memory application cache for all kinds of data.
  • Prevalence: uses Bamboo.Prevalence as the cache provider. Bamboo.Prevalence is a .NET implementation of the object prevalence concept brought to life by Klaus Wuestefeld in Prevayler. Bamboo.Prevalence provides transparent object persistence to deterministic systems targeting the CLR. It offers persistent caching for smart client applications.
  • SysCache: Uses System.Web.Caching.Cache as the cache provider. This means that you can rely on ASP.NET caching feature to understand how it works.
  • SysCache2: Similar to NHibernate.Caches.SysCache, uses ASP.NET cache. This provider also supports SQL dependency-based expiration, meaning that it is possible to configure certain cache regions to automatically expire when the relevant data in the database changes.
  • MemCache: uses memcached; memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load. Basically a distributed hash table.
  • SharedCache: high-performance, distributed and replicated memory object caching system. See here and here for more info

Saving a transient entity

Lately the following question came up in the NHibernate user list. "When I create a transient object and then save it to my session and
commit to my database, should it be added to my second level cache as well?" The answer is of course YES. Let's write a unit test

[TestFixture]
public class when_saving_a_transient_account : FixtureBase
{
    private Account newAccount;
 
    protected override void Context()
    {
        base.Context();
        using (var session = SessionFactory.OpenSession())
        using (var tx = session.BeginTransaction())
        {
            newAccount = new Account("CHF Account", 5500m);
            session.Save(newAccount);
            tx.Commit();
        }
    }
 
    [Test]
    public void account_should_be_in_second_level_cache()
    {
        using (var session = SessionFactory.OpenSession())
        {
            Console.WriteLine("--> Now loading account");
            var acc = session.Get<Account>(newAccount.Id);
            acc.ShouldNotBeNull();
            acc.Name.ShouldEqual(newAccount.Name);
        }
    }
}

In the method Context I create and save a new account entity. In the test method I open a new session and try to load the previously created entity from database. I now expect that NHibernate should take the entity out of the second level cache. And indeed it does. This is the resulting output

SecondLevelCache3

as we can see, no select statement is sent to the database when the entity is loaded from a new session after it has been created and saved beforehand.

Inside the second level cache

An important point is that the second-level cache does not cache instances of the object type being cached; instead it caches the individual values of the properties of that object. This provides two benefits. One, NHibernate doesn't have to worry that your client code will manipulate the objects in a way that will disrupt the cache. Two, the relationships and associations do not become stale, and are easy to keep up-to-date because they are simply identifiers. The cache is not a tree of objects but rather a map of arrays.

If you are interested in some more details about the inner workings of the second level cache then the following text (taken from Ayende and only slightly edited by me) will be of interest to you:

NHibernate is design as an enterprise OR/M product, and as such, it has very good support for running in web farms scenarios. This support include running along side with distributed caches, including immediate farm wide updates.  NHibernate goes to great lengths to ensure cache consistency in these scenarios...

The way it works, NHibernate keeps three caches.

  • The entities cache - the entity data is disassembled and then put in the cache, ready to be assembled to entities again.
  • The queries cache - the identifiers of entities returned from queries, but no the data itself (since this is in the entities cache).
  • The update timestamp cache - the last time a table was written to.

The last cache is very important, since it ensures that the cache will not serve stale results.

Now, when we come to actually using the cache, we have the following semantics.

  • Each session is associated with a timestamp on creation.
  • Every time we put query results in the cache, the timestamp of the executing session is recorded.
  • The timestamp cache is updated whenever a table is written to, but in a tricky sort of way:
    • When we perform the actual writing, we write a value that is somewhere in the future to the cache. So all queries that hit the cache now will not find it, and then hit the DB to get the new data. Since we are in the middle of transaction, they would wait until we finish the transaction. If we are using low isolation level, and another thread / machine attempts to put the old results back in the cache, it wouldn't hold, because the update timestamp is into the future.
    • When we perform the commit on the transaction, we update the timestamp cache with the current value.

Now, let us think about the meaning of this, shall we?

If a session has perform an update to a table, committed the transaction and then executed a cache query, it is not valid for the cache. That is because the timestamp written to the update cache is the transaction commit timestamp, while the query timestamp is the session's timestamp, which obviously comes earlier.

The update timestamp cache is not updated until you commit the transaction! This is to ensure that you will not read "uncommitted values" from the cache.

Please note that if you open a session with your own connection, it will not be able to put anything in the cache (all its cached queries will have an invalid timestamp!)

In general, those are not things that you need to concern yourself with, but I spent some time today just trying to get tests for the second level caching working, and it took me time to realize that in the tests I didn't used transactions and I used the same session for querying as for performing the updates.

Collections and the second level cache

Let's assume the following scenario: we have a blog which can have many posts. See the diagram below.
Blog diagram
The corresponding code to define the entities is as follows

public class Blog
{
    public virtual int Id { get; set; }
    public virtual string Author { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Post> Posts { get; set; }
 
    public Blog()
    {
        Posts = new List<Post>();
    }
 
}
 
public class Post
{
    public virtual int Id { get; private set; }
    public virtual string Title { get; set; }
    public virtual string Body { get; set; }
}

and we can define the mapping of the blog and the post entity like this

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   namespace="Caching"
                   assembly="Caching">
  <class name="Blog">
    <cache usage="read-write"/>
    <id name="Id">
      <generator class="hilo"/>
    </id>
    <property name="Author"/>
    <property name="Name"/>
    <bag name="Posts" cascade="all" lazy="true">
      <cache usage="read-write"/>
      <key column="BlogId"/>
      <one-to-many class="Post"/>
    </bag>
  </class>
  
  <class name="Post">
    <cache usage="read-write"/>
    <id name="Id">
      <generator class="hilo"/>
    </id>
    <property name="Title"/>
    <property name="Body"/>
  </class>
</hibernate-mapping>

Note that I have added a <cache> element to the mapping for the Blog entity. This is enough to cache all simple Blog property values (e.g. Id, Name and Author) but not the state of associated entities or collections. Collections require their own <cache> element. In our case I added a <cache> element to the Posts collection (which is mapped as a bag). This cache will be used when enumeration the collection blog.Posts, for example. Please be aware that a collection cache only holds the identifiers of the associated post instances. That is, if we have a blog with three posts having id's 1,2 and 3 respectively then the second level cache will contain the values of simple properties of the blog and in addition an array with the ids {1,2,3}. If we require the post instances themselves to be cached, then we must enable caching of the Post class by adding a <cache> element to it's mapping.

Let me resume: by adding a <cache> element to the Blog, the Posts collection and the Post itself I have declared that I want NHibernate to cache not only my blog entities but also the associated Post collection in full detail.

Attention: dragons ahead

A common error (It happened to me as well!) is to forget to commit or omit a transaction when adding or changing an entity/aggregate to the database. If we now access the entity/aggregate from another session then the 2nd level cache will not be prepared to provide us the cached instances and NHibernate makes an (unexpected round trip to the database). The reason why this is the case is described in the chapter "Inside the second level cache" above.

What does this mean? Let's have a look at the code I use to setup the context for our unit tests regarding the Blog-->Posts problem.

blog = new Blog{ Author = "Gabriel", Name = "Keep on running"};
blog.Posts.Add(new Post{Title = "First post", Body = "Some text"});
blog.Posts.Add(new Post { Title = "Second post", Body = "Some other text" });
blog.Posts.Add(new Post { Title = "Third post", Body = "Third post text" });
using (var session = SessionFactory.OpenSession())
using(var tx = session.BeginTransaction())
{
    session.Save(blog);
    tx.Commit();        // important otherwise caching does NOT work!
}

In the above code I create a new blog having three assigned posts. The blog instance is then saved to the database inside a transaction. If I would omit the transaction or if I would forget to commit the transaction then the above samples would not work as expected and the 2nd level cache would not be used as desired.

Caching queries in the second level cache

We cannot only cache entities loaded by their respective unique id but also any query. For this we have to define the query as cacheable and set the desired cache mode. Let's have a look at a typical sample

[Test]
public void trying_to_cache_a_query()
{
    using (var session = SessionFactory.OpenSession())
    {
        Console.WriteLine("---> using query first time");
        var query = session
            .CreateQuery("from Blog b where b.Author = :author")
            .SetString("author", "Gabriel")
            .SetCacheable(true);
        var list = query.List<Blog>();
    }
    using (var session = SessionFactory.OpenSession())
    {
        Console.WriteLine("---> using query second time");
        var query2 = session
            .CreateQuery("from Blog b where b.Author = :author")
            .SetString("author", "Gabriel")
            .SetCacheable(true);
        var list2 = query2.List<Blog>();
    }
}

In the above sample I use the same query from different sessions. Please not that I have set cacheable to true for the query. In this case the query will be cached in the second level cache the first time it is executed. Any subsequent calls using the very same query will not hit the database. It is important to note however that if I change the value of the parameter(s) in the query then the query is reloaded again from the database. So it is the query and the set of parameter values that define the key under which the query is stored in the 2nd level cache.

The result of the above test looks as follows

 CachQuery1 

Of course I can also use named queries and cache them. A named query is defined inside a mapping file, e.g.

<query cacheable="true" cache-mode="normal" name="query1">
  <![CDATA[from Blog b where b.Name like :name]]>
  <query-param name="name" type="String"/>
</query>

The above query is called "query1" and has a single parameter called "name". The cache mode for this query is set to "normal". I can use such a query as follows

[Test]
public void trying_named_query()
{
    using (var session = SessionFactory.OpenSession())
    {
        Console.WriteLine("---> using named query first time");
        var list = session.GetNamedQuery("query1")
            .SetString("name", "Keep%")
            .List<Blog>();
    }
    using (var session = SessionFactory.OpenSession())
    {
        Console.WriteLine("---> using named query second time");
        var list2 = session.GetNamedQuery("query1")
            .SetString("name", "Keep%")
            .List<Blog>();
    }
}

The session object has a method GetNamedQuery to retrieve the query. The output produced by the above test is then

CachQuery2
If the content of the table on which the cached query is based is changed then the query is evicted from the second level cache and the next time the query is executed the query must be reloaded.

Cache Regions

If we don't use cache regions the second level cache can only be cleared as a whole. If you need to clear only part of the second level cache then use regions. Regions are distinguished by their name. One can put any number of different queries into a named cache region. The command to clear a cache region is as follows
    SessionFactory.EvictQueries("My Region");
where SessionFactory is the session factory instance currently used and "My Region" is the name of the cache region.

Source Code

The full source code used for this post can be found here.

Summary

NHibernate provides two types of caches. The first level cache and the second level cache. The first level cache is also called the identity map and is used not only to reduce the number of round trips to the database to improve the speed of an application but also to guarantee that there do not exist two distinct instances of an object having the very same id. NHibernate provides us two methods to load an entity by its unique id from the database. The Get method returns null if an entity with the given id does not exist or returns the fully loaded entity to the caller. The Load method on the other hand returns a proxy to the caller and only loads the entity from the database if another property than the identity is accessed. One can also call this a deferred load.

The second level cache is not used by default and should be used with caution. It can provide a huge scalability gain if used wisely but also reduce the performance of the overall system and introduce unnecessary complexity if used wrong.

The second level cache is related to the session factory, that is all session instances of a given session factory use the same 2nd level cache. That's differs from the behavior of the 1st level cache which is related to an individual session instance. One can cache individual entities or whole aggregates in the 2nd level cache. But one can also cache (complex and/or time consuming) queries in the 2nd level cache. The 2nd level cache can be fragmented into regions for a more fine grained control.

Enjoy.

Blog Signature Gabriel

Published at

The Repository Pattern

Introduction

When accessing data from a data source we have several well documented possibilities. Martin Fowler e.g. describes several of them in his PoEAA book.

  • Table data gateway
  • Row data gateway
  • Active record
  • Data mapper

When applying DDD (domain driven design) we often use the so called Repository Pattern to access the data needed by the domain model.

What is a Repository

Martin Fowler writes:

"A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers."

Implementation

In DDD we have the notion of aggregates. An aggregate is "A cluster of associated objects that are treated as a unit for the purpose of data changes. External references are restricted to one member of the Aggregate, designated as the root. A set of consistency rules applies within the Aggregate's boundaries.".

Usually one defines a repository per aggregate in the domain. That is: we don't have a repository per entity! If we have a look at a simple order entry system the entity Order might be the root of a Order aggregate. Thus we will have an Order Repository.

The interface (or contract) of the repository is considered as a part of the domain model where as the implementation of the repository is infrastructure specific and thus does NOT belong to the domain model.

When dealing with aggregates most of the time we need exactly 3 persistence related operations

  • get an aggregate by it's id (primary key)
  • add a new aggregate to the repository
  • remove an aggregate from the repository

Depending on the context there might be other persistence related operations that are needed but the most common and often used ones are the three mentioned above. This leads us to the following minimal contract (interface) with the repository

public interface IOrderRepository
{
    Order GetById(int id);
    void Add(Order order);
    void Remove(Order order);
}

In the above sample we assume that the primary key of the Order is a surrogate key and is of type int.

Now let's assume that we have identified a second aggregate in our domain model, the Product aggregate. Then we can immediately deduce the appropriate repository interface from the interface to the order repository. We have

public interface IProductRepository
{
    Product GetById(int id);
    void Add(Product product);
    void Remove(Product product);
}

Now this looks very similar to the first interface and we can generalize the interface by using a generic parameter. We then have

public interface IRepository<T>
{
    T GetById(int id);
    void Add(T entity);
    void Remove(T entity);
}

Now the interfaces to the product and the order repository will just be

public interface IOrderRepository : IRepository<Order> { }
public interface IProductRepository : IRepository<Product> { }

A fake repository

For testing purposes we can implement a fake repository for the product aggregate. In this case it will be a dictionary with some predefined products. The key to each product will be its primary key. In our simple sample the Product aggregate consists only of the Product entity

public class Product
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual int ReorderLevel { get; set; }
    public virtual bool Discontinued { get; set; }
}

This is a very simple entity but it is sufficient for our purposes. Now let's have a look at the implementation of the faked repository

public class ProductRepositoryFake : IProductRepository
{
    private readonly Dictionary<int, Product> dictionary;
 
    public ProductRepositoryFake()
    {
        dictionary = new Dictionary<int, Product>();
        dictionary.Add(1, new Product {Id = 1, Name = "Product 1", ReorderLevel = 10, Discontinued = false});
        dictionary.Add(2, new Product {Id = 2, Name = "Product 2", ReorderLevel = 15, Discontinued = false});
        dictionary.Add(3, new Product {Id = 3, Name = "Product 3", ReorderLevel = 10, Discontinued = false});
        dictionary.Add(4, new Product {Id = 4, Name = "Product 4", ReorderLevel = 12, Discontinued = false});
        dictionary.Add(5, new Product {Id = 5, Name = "Product 5", ReorderLevel = 20, Discontinued = true});
    }
 
    public Product GetById(int id)
    {
        return dictionary[id];
    }
 
    public void Add(Product product)
    {
        dictionary.Add(product.Id, product);
    }
 
    public void Remove(Product product)
    {
        dictionary.Remove(product.Id);
    }
}

In the constructor I instantiate a dictionary which takes as key an int (the type of the primary key in our case) and as value a Product instance. Then I define several sample Product instances which I fill into the dictionary. The implementation of the three methods GetById, Add and Remove is straight forward and needs no further explanation.

Now let's write some unit tests where we use this implementation of the repository. Note that the special methods (e.g. ShouldEqual, ShouldNotBeNull, ShouldBeThrownBy, etc.) found in the code below are extension methods and can be found in the code accompanying this post. They aid to make the test code more readable than when using the Assert.Equals(...), etc. syntax.

[TestFixture]
public class FakeRepositoryTester
{
    private IProductRepository repository;
 
    [SetUp]
    public void SetupContext()
    {
        repository = new ProductRepositoryFake();
    }
 
    [Test]
    public void can_load_a_product_by_its_id_from_the_repository()
    {
        var product = repository.GetById(2);
 
        product.ShouldNotBeNull();
        product.Id.ShouldEqual(2);
    }
 
    [Test]
    public void can_add_a_new_product_to_the_repository()
    {
        repository.Add(new Product {Id = 99, Name = "Product 99", ReorderLevel = 13, Discontinued = false});
        
        // let's try to load this new product
        var product = repository.GetById(99);
        product.Id.ShouldEqual(99);
        product.Name.ShouldEqual("Product 99");
    }
 
    [Test]
    public void can_remove_an_existing_product_from_the_repository()
    {
        var product = repository.GetById(1);
        repository.Remove(product);
 
        typeof (KeyNotFoundException).ShouldBeThrownBy(() => repository.GetById(1));
    }
}

In the SetupContext method (which will be executed before each test) I define the repository to be an instance of type ProductRepositoryFake. Note that the repository field is declared as type of IProductRepository!

The first test method verifies that the GetById method works as expected. Which indeed it does since when running the test it is green. The second test verifies that the Add method works. First I add a new (non existing) product instance. Then I immediately try to reload this new instance by its id. Then the reloaded instance is tested whether it is the one expected (by comparing some of its properties).

Last but not least the third method tests the Remove method. In the first line I load a product instance from the repository which I know exists. This instance is then removed from the repository. In the third line I test whether the product was really removed from the repository by expecting an exception when trying to get the (previously removed) product from the repository again.

Please note that in the above test code there is only one place where the specific implementation of the repository is of interest. It's the line in the SetupContext method where the repository instance is created. The rest of the code is fully agnostic regarding the specific implementation of the repository. That's an important fact to remember. That means that I can exchange the implementation used in the above code by only changing a single line of code!

An implementation for NHibernate

Now let's try a first implementation for the repository that uses NHibernate. First I need a session provider. I use the following implementation

public class SessionProvider
{
    private static Configuration configuration;
    private static ISessionFactory sessionFactory;
 
    public static Configuration Configuration
    {
        get
        {
            if(configuration == null)
            {
                configuration = new Configuration();
                configuration.Configure();                              // A
                configuration.AddAssembly(typeof (Product).Assembly);   // B
            }
            return configuration;
        }
    }
 
    public static ISessionFactory SessionFactory
    {
        get
        {
            if (sessionFactory == null)
                sessionFactory = Configuration.BuildSessionFactory();
            return sessionFactory;
        }
    }
 
    private SessionProvider()
    { }
 
    public static ISession GetSession()
    {
        return SessionFactory.OpenSession();
    }
}

In the above sample code the session factory is only built on demand and only once during the life-time of the application (the construction of the session factory is an expensive operation, on the other hand the session factory is thread safe). I make the following assumptions

  • the existence of a hibernate.cfg.xml for configuration of the connection properties (A)
  • all mapping files for the domain entities can be found in the assembly where the Product entity is defined (B)

With the aid of this SessionProvider class the implementation of the repository for e.g. the Product entity is really trivial

public class ProductRepositoryNH : IProductRepository
{
    private static ISession GetSession() { return SessionProvider.GetSession(); }
 
    public Product GetById(int id)
    {
        using (var session = GetSession())
            return session.Get<Product>(id);
    }
 
    public void Add(Product product)
    {
        using (var session = GetSession())
            session.Save(product);
    }
 
    public void Remove(Product product)
    {
        using (var session = GetSession())
            session.Delete(product);
    }
}

We have a private helper function GetSession which just returns a new session object whenever accessed. The other methods use this helper property for their operations. Note the usage of the using statement to guarantee that the session object is released whenever the database operation is finished.

But the above implementation (although working) has an important flaw and thus can hardly be used in a real application! It's the fact that the repository uses a different session instance for each operation. In a real application often several operations have to be executed inside a single transaction and thus inside a single session (the reason is that a transaction cannot span multiple sessions - at least when not using distributed transactions).

The Unit of Work to the rescue

We can resolve the above dilemma by applying the Unit of Work (UoW) pattern (for a profound discussion of this patterns please refer to this article)! The UoW manages a session for us. I can then refactor my implementation of the product repository as follows

public class ProductRepository : IProductRepository
{
    private ISession Session { get { return UnitOfWork.CurrentSession; } }
 
    public Product GetById(int id)
    {
        return Session.Get<Product>(id);
    }
 
    public void Add(Product product)
    {
        Session.Save(product);
    }
 
    public void Remove(Product product)
    {
        Session.Delete(product);
    }
}

Unit Tests

First I implement a base class for unit testing repositories. This base class configures my unit of work and re-creates the schema for each test (I'm using SqLite in in-memory mode as my database)

public class RepositoryFixtureBase<T>
{
    [TestFixtureSetUp]
    public void TestFixtureSetup()
    {
        UnitOfWork.Configuration.AddAssembly(typeof(T).Assembly);
    }
 
    [SetUp]
    public void SetupContext()
    {
        UnitOfWork.Start();
 
        new SchemaExport(UnitOfWork.Configuration)
            .Execute(false, true, false, false, UnitOfWork.CurrentSession.Connection, null);
 
        Context();
    }
 
    [TearDown]
    public void TearDownContext()
    {
        UnitOfWork.Current.TransactionalFlush();
        UnitOfWork.Current.Dispose();
    }
 
    protected virtual void Context() { }
}

with the aid of the above base class the unit tests for my product repository look like this

[TestFixture]
public class ProductRepository_Tester : RepositoryFixtureBase<Product>
{
    private IProductRepository repository;
    private Product[] products;
 
    protected override void Context()
    {
        products = new[]
                       {
                           new Product {Id = 1, Name = "Product 1", ReorderLevel = 10, Discontinued = false},
                           new Product {Id = 2, Name = "Product 2", ReorderLevel = 15, Discontinued = false},
                           new Product {Id = 3, Name = "Product 3", ReorderLevel = 10, Discontinued = false},
                           new Product {Id = 4, Name = "Product 4", ReorderLevel = 12, Discontinued = false},
                           new Product {Id = 5, Name = "Product 5", ReorderLevel = 20, Discontinued = true},
                       };
        
        foreach (var product in products)
            UnitOfWork.CurrentSession.Save(product);
 
        UnitOfWork.CurrentSession.Flush();
        UnitOfWork.CurrentSession.Clear();
 
        repository = new ProductRepository();
    }
 
    [Test]
    public void can_load_product()
    {
        var p = repository.GetById(2);
        p.ShouldNotBeNull();
        p.Id.ShouldEqual(products[1].Id);
    }
 
    [Test]
    public void can_add_a_product_to_the_repository()
    {
        repository.Add(new Product { Id = 6, Name = "Product 6", ReorderLevel = 6, Discontinued = false });
 
        UnitOfWork.CurrentSession.Flush();
        UnitOfWork.CurrentSession.Clear();
        var prod = UnitOfWork.CurrentSession.Get<Product>(6);
        prod.ShouldNotBeNull();
    }
 
    [Test]
    public void can_remove_product_from_repository()
    {
        repository.Remove(products[2]);
 
        UnitOfWork.CurrentSession.Flush();
        UnitOfWork.CurrentSession.Clear();
        var prod = UnitOfWork.CurrentSession.Get<Product>(products[2].Id);
        prod.ShouldBeNull();
    }
}

In the Context method (which is executed before each test) I set up my boundary conditions (=the context). I define an array of products which are then inserted into the database. After inserting these products the current session is flushed and then cleared.

In the first test method can_load_product I try to load a product with the id equal to 2. This product exists in the database since I have applied the boundary conditions. After loading the product I check whether it has really been loaded (ShouldNotBeNull) and that I indeed received the product with the requested id.

In the second test method can_add_a_product_to_the_repository I first try to add a new product instance to the repository. I then flush the current session and clear it. Then I try to re-load the new product from the repository and verify that it is not null. Note that if I wouldn't clear the session after inserting the product, the product would still be in the first level cache and NHibernate would not query the database when I execute the ...Get<Product>(id) method but rather return the object in the cache.

In the third and last test method can_remove_product_from_repository test I try to remove an existing product from the repository. Now when trying to reload the deleted product I should get null.

A generic base repository

When having a look again at our product repository (and possibly at the order repository whose implementation I leave as an exercise for you) we can see some room left for improvement. What if I implement a base repository which in a generic way implements all the common functionality. This leads to the following implementation

public class Repository<T> : IRepository<T>
{
    public ISession Session { get { return UnitOfWork.CurrentSession; } }
 
    public T GetById(int id)
    {
        return Session.Get<T>(id);
    }
 
    public ICollection<T> FindAll()
    {
        return Session.CreateCriteria(typeof(T)).List<T>();
    }
 
    public void Add(T product)
    {
        Session.Save(product);
    }
 
    public void Remove(T product)
    {
        Session.Delete(product);
    }
}

I have taken the code from the ProductRepository class and just replaced any occurrence of Product with the generic parameter T.

Note that this base class can now easily be extended to contain more functionality which is used across repositories for different entities. As an example I have added a FindAll method in the above implementation which just returns a list of all items of the specific type.

Do we still need the ProductRepository and/or OrderRepository classes? Well, it depends. If our application has no other needs regarding the product and order repository then no, we can just use the generic base repository. On the other hand if we want to provide a specific query for the product aggregate (which in turn makes no sense for the order aggregate) we explicitly define a product repository which is a child of the generic base repository.

Let's take this as an example

public interface IProductRepository : IRepository<Product>
{
    ICollection<Product> FindAllDiscontinuedProducts();
}

Here I have declared the need for a query that returns the list of discontinued products (note that there is no notion of discontinued orders...). The implementation is straight forward

public class ProductRepository : Repository<Product>, IProductRepository
{
    public ICollection<Product> FindAllDiscontinuedProducts()
    {
        return Session.CreateCriteria(typeof (Product))
            .Add(Restrictions.Eq("Discontinued", true))
            .List<Product>();
    }
}

The above method hides the infrastructure related details from my domain and/or application and provides a business friendly interface

Let's have a look how I can test the above method

public void can_load_all_discontinued_products()
{
    var discontinuedProducts = repository.FindAllDiscontinuedProducts();
 
    discontinuedProducts.Count.ShouldBeGreaterThan(0);
    discontinuedProducts.ToList().ForEach(p=>p.Discontinued.ShouldBeTrue());
}

I expect the method to return at least 1 product and each returned product should have its property Discontinued set to true.

Code

The code to this post can be found here.

Summary

I have discussed the repository pattern which is used to retrieve data from external data sources (e.g. databases) in an easy and consistent way. Its main benefit is a clean separation of the domain and the data mapping layer. I have presented an implementation of the pattern for NHibernate. This implementation makes use of the Unit of Work which is another well known pattern which I have introduced in a previous post.

Enjoy

Blog Signature Gabriel

Published at

Value objects

Introduction

Eric Evans writes in his DDD book:

When you care only about the attributes of an element of the model, classify it as a value object. Make it express the meaning of the attributes it conveys and give it related functionality. Treat the value object as immutable. Don't give it any identity and avoid the design complexities necessary to maintain entities.

Many objects have no conceptual identity. These objects describe some characteristic of a thing.

A value object is an object that describes some characteristics or attribute but carries no concept of identity .

Samples

There are many samples where the introduction of a value object is useful. One of the most used value objects in DDD is certainly the Money value object. There is even a pattern called after this value object (the money pattern).

money

A large proportion of the computers in this world manipulate money. But money isn't a first class data type on the .Net framework. The lack of a type causes problems, the most obvious surrounding currencies. If all your calculations are done in a single currency, this isn't a huge problem, but once you involve multiple currencies you want to avoid adding an amount expressed in dollars to an amount expressed in Euro without taking the currency differences into account. Also rounding is a problem. Monetary calculations are often rounded to the smallest currency unit (pennies for dollar and cent for Euro).

Another typical example of a value object is an Address. The address is even a very interesting beast, since it contains a reference to Country which in turn often is treated like an entity.

 address

Yet another example is a geographical coordinate. It consists of the two values longitude and latitude.

 GeoCoordinate

Often we see people introduce a value object for the names of a person. Such a name value object could e.g. consist of the three members first name, middle name and last name where the first and the last are mandatory and the middle name is optional.

 name

Finally another well known value object is Color. Color is a structure which normally consist of four values (red, green, blue and alpha)

color

Note that the alpha channel is an indicator for the transparency of a colored shape. It goes from completely transparent (0) to opaque (255).

Immutability

As told earlier a value object should always be immutable. The consequence of this is that once its properties are set they cannot be changed. The best way to guarantee this is that all properties are read-only (they have private or no setter methods). A new instance of a value object is completely defined through its constructor. Let's take as a sample the Name value object.

public class Name
{
    public string FirstName { get; private set; }
    public string MiddleName { get; private set; }
    public string LastName { get; private set; }
 
    public Name(string firstName, string middleName, string lastName)
    {
        FirstName = firstName;
        MiddleName = middleName;
        LastName = lastName;
    }
}

Validation

Since a value object is immutable it makes sense that each value object must always be in a valid state. The validation happens in the constructor of the value object. Again let's look at the Name value object as an example. Below I present the constructor of the value object. This time with the validation logic.

public Name(string firstName, string middleName, string lastName)
{
    // Validation logic
    if(string.IsNullOrEmpty(firstName)) 
        throw new ArgumentException("First name cannot be undefined.");
    if(string.IsNullOrEmpty(lastName)) 
        throw new ArgumentException("Last name cannot be undefined.");
 
    if(firstName.Length>50)
        throw new ArgumentException("Length of first name cannot exceed 50 characters.");
    if(middleName.Length>30)
        throw new ArgumentException("Length of middle name cannot exceed 30 characters.");
    if(lastName.Length>50)
        throw new ArgumentException("Length of last name cannot exceed 50 characters.");
 
    FirstName = firstName;
    MiddleName = middleName;
    LastName = lastName;
}

The validation logic checks that the first and last name are given and that any of the names does not exceed the maximal tolerated length. If the validation tests have all passed then we are sure that our value object is now in a valid state. From now on we will never again have to make validation check against our Name instance. You should not underestimate the positive consequences of this!

Equality

It is very important that two instances of a value object are comparable, that is whether they contain the same values in their constituent properties. To achieve this we have to at least override the two sister methods Equals and GetHashCode which are inherited from the base class System.Object.

But we should also implement the generic interface IEquatable<T> in our value object to provide a type safe method for comparing two instances.

public class Name : IEquatable<Name>
{
    // omitted code for brevity...
 
    public override int GetHashCode()
    {
        return string.Format("{0}|{1}|{2}", FirstName, MiddleName, LastName).GetHashCode();
    }
 
    public override bool Equals(object obj)
    {
        return Equals(obj as Name);
    }
 
    public bool Equals(Name other)
    {
        if(other==null) return false;
        return FirstName.Equals(other.FirstName) &&
               ((MiddleName == null && other.MiddleName == null) ||
                (MiddleName != null && MiddleName.Equals(other.MiddleName))) &&
                LastName.Equals(other.LastName);
    }
}

Note that my implementation of GetHashCode is certainly not the unique or best implementation. But it is easy and works for me.

In the Equals method I compare the two instances of the value object property by property. Since the middle name is optional it can be null and thus needs a special treatment.

For convenience we can also override the operators == and != as follows

public static bool operator ==(Name left, Name right)
{
    return Equals(left, right);
}
 
public static bool operator !=(Name left, Name right)
{
    return !Equals(left, right);
}

this allows me to use such constructs as

if(name1 == name2) {...}    or

if(name1 != name2) {...}.

Builders

Creating an instance of a value object can be error prone when using the constructor. The code is not very readable. How should I know whether the following code fragment is correct?

address = new Address("Paradise Street 12", "P.O.Box 233", "Neverland", "82344", unitedStates);

Could it possibly be that the postal code and the city are confused? How should I know. Just by reading I have no idea since the code is not self describing. So, is this the correct version?

address = new Address("Paradise Street 12", "P.O.Box 233", "82344", "Neverland", unitedStates);

Note that both versions compile, but only the first one is correct. To eliminate this weakness people often implement object builders for complex value objects like an address. Often a builder implements some kind of fluent interface to make the code very self explaining and compact (free of syntactic noise!).

address = new AddressBuilder()
    .AddressLine1("Paradise Steet 12")
    .AddressLine2("P.O.Box 233")
    .PostalCode("82344")
    .City("Neverland")
    .Country(unitedStates);

The above code snippet is very self expressing, isn't it?

How is such a builder implemented? Let's have a look at a possible solution

public class AddressBuilder
{
    internal string addressLine1;
    internal string addressLine2;
    internal string city;
    internal string postalCode;
    internal Country country;
 
    [DebuggerStepThrough]
    public AddressBuilder AddressLine1(string line)
    {
        addressLine1 = line;
        return this;
    }
 
    [DebuggerStepThrough]
    public AddressBuilder AddressLine2(string line)
    {
        addressLine2 = line;
        return this;
    }
 
    [DebuggerStepThrough]
    public AddressBuilder PostalCode(string code)
    {
        postalCode = code;
        return this;
    }
 
    [DebuggerStepThrough]
    public AddressBuilder City(string city)
    {
        this.city = city;
        return this;
    }
 
    [DebuggerStepThrough]
    public AddressBuilder Country(Country country)
    {
        this.country = country;
        return this;
    }
 
    public static implicit operator Address(AddressBuilder builder)
    {
        return new Address(builder.addressLine1, builder.addressLine2, builder.city, builder.postalCode, builder.country);
    }
}

Especially have a look at the implementation of the implicit operator!

Note that the DebuggerStepThrough attribute is used to avoid debugging through the builder code since the code can be assumed to be error free (it is trivial).

Object Mother

When following TDD (that is: write the test first and only then implement the code to satisfy the test...) we often need some sample data. In the case of a value object we can directly create such an instance in the test method. But this is not DRY since we will have a lot of code duplication. One possible solution is the introduction of a so called object mother. This is a class with static methods which delivers us prefabricated (valid) value objects.

An Object Mother is another name for a factory for test objects. It can be implemented as static class with appropriate methods, e.g.

public static class ObjectMother
{
    private static readonly Country unitedStates = new Country("USA", "United States of America");
    private static readonly Country switzerland = new Country("CH", "Switzerland");
 
    public static Address GetAddress()
    {
        return new AddressBuilder()
            .AddressLine1("Paradise Street 12")
            .AddressLine2("P.O.Box 233")
            .PostalCode("82344")
            .City("Neverland")
            .Country(unitedStates);
    }
 
    public static Address GetSwissAddress()
    {
        return new AddressBuilder()
            .AddressLine1("In der Matte 8")
            .PostalCode("3000")
            .City("Bern")
            .Country(switzerland);
    }
}

In the above sample I use the address builder introduced above to create sample value objects of type address.

Depending on the needs we can have one or several method for any object type we need (or even several overloads of a method if we want to have some configurability of the created objects...).

Enum type value objects

A special variant of a value object is a value object whose base is a enum type. Let me give some samples:

Let's assume we have a task entity. A task object has a state which can have any of the following values

public enum TaskStatusEnum
{
    Undefined = 0,
    Pending,
    InProgress,
    Done
}

But the direct usage of an enum type is unhandy in a domain model. Thus I never use an enum type directly as a value object but rather encapsulate it in a class. A possible implementation for this would be

public class TaskStatus
{
    public TaskStatusEnum Status { get; private set; }
    public string Description { get { return Status.ToString(); } }
 
    public TaskStatus(TaskStatusEnum status)
    {
        Status = status;
    }
}

Instances of the TaskStatus class are value objects. Only the property Status is mapped to the database. The Name property is only for visual representation of a task status (on a view). Of course I would have to implement the IEquality<T> interface in the above class as well as override the Equals and GetHashCode methods. But I have omitted this for brevity.

For convenience I normally implement also a static property get for any of the possible values of the enum in the above class, that is

public static TaskStatus Undefined { get { return new TaskStatus(TaskStatusEnum.Undefined); } }
public static TaskStatus Pending { get { return new TaskStatus(TaskStatusEnum.Pending); } }
public static TaskStatus InProgress { get { return new TaskStatus(TaskStatusEnum.InProgress); } }
public static TaskStatus Done { get { return new TaskStatus(TaskStatusEnum.Done); } }

As you can see it's a little bit more overhead over using an enum directly but it's definitely worth the effort. You gain all the advantages a value object offers you.

Value objects and NHibernate

When we deal with NHibernate a value object is represented by a -->Component. A value object is not stored in a separate table but rather embedded in the table related to the containing entity. That is, if I have an Account entity which contains a property Balance which in turn is a value object (of type Money) then I only have a table Account in the database (but no Money table) and the fields of the Balance value object are part of the Account table.

Mapping

How are value objects mapped in NHibernate? I want to describe three possible ways how we can achieve the desired result. Let's take a (simplified) entity Account as an example

public class Account
{
    public Guid Id { get; set; }
    public string AccountNo { get; set; }
    public Money Balance { get; set; }
 
    // additional properties and logic
    // omitted for brevity...
}

XML mapping files

The most common way to describe the mapping between a domain model and the underlying database is by using XML mapping files.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Account">
    <id name="Id">
      <generator class="guidcomb"/>
    </id>
    <property name="AccountNo" not-null="true" length="20"/>
    
    <component name="Balance">
      <property name="Value"/>
      <property name="CurrencyCode"/>
    </component>
    
  </class>
</hibernate-mapping>

Note that the Money value object is mapped via the <component> tag in the mapping file.

Castle Active Record

If you are using Castle Active Record for your mapping then you just have to decorate the Balance property of the Account with the attribute [Nested].

[ActiveRecord]
public class Account
{
    [PrimaryKey]
    public Guid Id { get; set; }
    [Property]
    public string AccountNo { get; set; }
    [Nested("Balance")]
    public Money Balance { get; set; }
 
    // additional properties and logic
    // omitted for brevity...
}

You can provide as a parameter to the attribute the column prefix that will be used when mapped to the underlying database table. In the above example the fields in the Account table would be BalanceValue and BalanceCurrencyCode.

Fluent Interface

With the new Fluent NHibernate framework which I descibed here one can define the mapping as follows

public class AccountMap : ClassMap<Account>
{
    public AccountMap()
    {
        Id(x => x.Id);
 
        Map(x => x.AccountNo)
            .CanNotBeNull()
            .WithLengthOf(20);
 
        Component<Money>(
            x => x.Balance, m =>
                                {
                                    m.Map(x => x.Value, "BalanceValue");
                                    m.Map(x => x.CurrencyCode, "BalanceCurrencyCode");
                                });
    }
}

Note that the benefit of the fluent interface is not the brevity of the code but rather the robustness, testability of the mapping as well as the ability to include the mapping in any refactoring.

Summary

I have introduced you to the value object, which is a fundamental piece of DDD. Not only have I presented you the theory behind a value object but also shown you some possible implementation for immutability, validation and mapping of value objects. I also have shown how one can handle value objects which are based on a .Net enum. Further I introduced the concept of builders (for value objects) which help you make the code more readable (and thus maintainable). Last but not least I discussed the usage of the Object Mother pattern in the context of test driven development (TDD).

Enjoy

Blog Signature Gabriel

Published at

A fluent interface to NHibernate - Part 4 - Configuration

This is the fourth post in a series of articles where I want to analyze and describe the new upcoming mapping interface providing a fluent interface to NHibernate for the mapping of a domain model to the underlying database. The previous post are

Configuration

In NHibernate we traditionally had several methods how we could configure the database relevant parameters. These are

  • defining all requested configuration parameters in code
  • include a special section in the app.config or web.config file
  • define a hibernate.cfg.xml file
  • define a custom XML file

With the new mapping framework we have one more possibility by using a fluent interface to configure NHibernate. We can define all parameters in our code using a fluent interface. Let's review the various methods to configure our ORM framework.

Defining requested configuration parameters in code

When initializing the NHibernate framework I can configure all necessary parameters in code. I just instantiate a Configuration object and pass it all requested parameters via the SetProperty method. Having set all necessary connection parameters I can now define where my domain model is. In the sample below I take the AddAssembly method to tell NHibernate that all my model classes are to be found in the assembly where the class Blog is defined. NHibernate will then parse the whole assembly for embedded mapping files (e.g. Blog.hbm.xml etc.). In the last line of code I create the session factory. This factory instance I'll then use each time I need a connection to the database.

var cfg = new Configuration();
 
cfg.SetProperty("connection.provider", "NHibernate.Connection.DriverConnectionProvider");
cfg.SetProperty("connection.driver_class", "NHibernate.Driver.SQLite20Driver");
cfg.SetProperty("dialect", "NHibernate.Dialect.SQLiteDialect");
cfg.SetProperty("connection.connection_string", "Data Source=:memory:;Version=3;New=True;");
cfg.SetProperty("connection.release_mode", "on_close");
cfg.SetProperty("show_sql", "true");
 
cfg.AddAssembly(typeof (Blog).Assembly);
 
ISessionFactory factory = cfg.BuildSessionFactory();

In the above sample I'm using SqLite as my database and the connection string is configured such as that the database is in in-memory mode, that is the schema and the data is not written to disk but always kept in memory. I also have told NHibernate to output all SQL sent to the database to the console (for debugging purposes). This is the typical configuration I tend to use in my unit tests.

The app.config or web.config

This is an example of how to specify the database connection properties inside a web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="hibernate-configuration"         
             type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
  </configSections>
  
  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
      <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
      <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
      <property name="connection.connection_string">Server=(local);database=thedatabase;Integrated Security=SSPI;</property>
      <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
      <property name="show_sql">true</property>
    </session-factory>
  </hibernate-configuration>
  
  <!-- other app specific config follows... -->
  
</configuration>
 

You first have to define a section for NHibernate in the configSections part of the config file. The content of the NHibernate section is then the same as when you use the hibernate.cfg.xml file (see below). In this sample I'm using an SQL Server 2005 database which is installed on the local machine. The connection to the SQL Server uses integrated security. I also have told NHibernate to output all SQL sent to the database to the console.

Now I can initialize NHibernate with the following code

var cfg = new Configuration();
cfg.AddAssembly(typeof (Product).Assembly);
ISessionFactory factory = cfg.BuildSessionFactory();

Note that the necessary configuration parameters are automatically picked up by NHibernate from the app.config or web.config file.

The hibernate.cfg.xml file

Below I present a typical configuration file. Again this sample assumes SqLite as my database.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="dialect">NHibernate.Dialect.SQLiteDialect</property>
    <property name="connection.driver_class">NHibernate.Driver.SQLite20Driver</property>
    <property name="connection.connection_string">Data Source=:memory:;Version=3;New=True;</property>
    <property name="connection.release_mode">on_close</property>
 
    <property name="show_sql">true</property>
  </session-factory>
</hibernate-configuration>

This file must be present in the same directory as the application that uses it. Then NHibernate can automatically pick it up when you initialize the framework.

var cfg = new Configuration();
cfg.Configure();
 
cfg.AddAssembly(typeof (Blog).Assembly);
 
ISessionFactory factory = cfg.BuildSessionFactory();

We have to instantiate a NHibernate Configuration object and call the method Configure. When doing this the default behavior is that NHibernate looks for a file called hibernate.cfg.xml in the application directory an opens it if available.

A custom XML file

The content of the file must be structured the same way as in the hibernate.cfg.xml presented above. But you can name the file however you want and you are also free to choose it's location. When you initialize NHibernate you have to provide the respective information about your configuration file.

You can pick a different XML configuration file using the following syntax

var cfg = new Configuration();
cfg.Configure(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"my_config_file.xml"));
 
cfg.AddAssembly(typeof(Product).Assembly);
 
ISessionFactory factory = cfg.BuildSessionFactory();

The method Configure accepts a parameter indicating the full path to my custom XML file.

Use a fluent interface to configure NHibernate

All the above samples are not really complicated but have the disadvantage that we have to deal with strings (configuration in code) or with XML. XML is not really nice to read and certainly not wrist friendly. Also there is no compile time error checking. Any typos introduced will only be detected during runtime.

Comes the fluent interface to the rescue. I can now configure NHibernate in a strongly typed fashion. Have a look at the following code

var cfg = new MyConfiguration()
    .ShowSql()
    .Driver<SQLite20Driver>()
    .Dialect<SQLiteDialect>()
    .ConnectionString.Is("Data Source=:memory:;Version=3;New=True;")
    .Raw("connection.release_mode", "on_close");

A few remarks to this code

  • no need to define a connection provider (it's always and has always bee NHibernate.Connection.DriverConnectionProvider and thus this is configured implicitly by the framework)
  • all commonly used parameters can be configured using strong typing
  • generic methods are used wherever flexibility is needed (e.g. the method .Driver<T>() where T represents the concrete driver you want to choose)
  • the method Raw can be used whenever we need to configure non-standard (that is database specific) parameters. In the sample above I define the connection release mode for the SqLite database.
  • The connection string can either be defined in place (as in the above sample) or
    • be retrieved from the appSection in the web.config or app.config file
      .ConnectionString.FromAppSetting("MyConnectionString")
    • be retrieved from the connectionStrings section in the web.config or app.config file
      .ConnectionString.FromConnectionStringWithKey("MyConnectionString")

There are other methods we can use to further configure NHibernate (e.g. UseOuterJoin, MaxFetchDepth and UseReflectionOptimizer)

Now I have to say some words to the MyConfiguration class used in the sample above... This class inherits from the PersistenceConfiguration class of the fluent interface framework and contains no code.

public class MyConfiguration : PersistenceConfiguration<MyConfiguration>
{
}

For some databases there are even pre-defined configuration classes that facilitate the job even further. For SqLite I can then write

var cfg = new SQLiteConfiguration()
    .InMemory()
    .DoNot.ShowSql();

Really nice! Please note also the DoNot... syntax to revert some boolean settings like ShowSql or UseOuterJoin, etc.

Now a complete sample how to configure and use NHibernate

var nhibernateConfig = new Configuration();
var cfg = new SQLiteConfiguration()
    .InMemory()
    .ConfigureProperties(nhibernateConfig);
 
var sessionSource = new SessionSource(cfg.Properties, new MyPersistenceModel());
 
using (var session = sessionSource.CreateSession())
{
    var product = new Product { Name = "Product 1", UnitPrice = 10.55m, Discontinued = false };
    session.Save(product);
}

First I instantiate an object of type NHibernate.Cfg.Configuration. I then instantiate an object of type SQLiteConfiguration which is defined in the mapping framework. With the ConfigureProperties method I tell this object to configure the NHibernate configuration object which I pass as a parameter. Then I instantiate a SessionSource object an pass it the properties of my SqLite configuration object as well as my persistence model. Last I use this session source to create a new session and insert a new product into the database. (Please refer to the previous articles of this series for a description of the persistence model).

Summary

Various methods exists how one can configure NHibernate. None of them is really complicated. But the new mapping framework facilitates the configuration even more and has the following advantages over the other methods

  • type safety (and thus also re-factor friendly)
  • good readability
  • intellisense support

Enjoy

Blog Signature Gabriel .

Published at

A fluent interface to NHibernate - Part 3 - Mapping Relations

This is the third post in a series of articles where I want to analyze and describe the new upcoming mapping interface providing a fluent interface to NHibernate for the mapping of a domain model to the underlying database. The other posts are

You can get the source code of the solution accompanying this post here.

In the time between my last post and today a lot has happened to the mapping framework. The contributors are busily improving the source and are also very responsive to my questions and remarks.

In this post I want to focus on how one can map various relations between entities and value objects of a domain model.

Scenario 3

Domain Model

Let's have a look at the following simplified model

image

I have a Blog which has an author of type Person. Each Blog can have many Posts. To each Post readers can give feedback in the form of Comments. Comments are considered value objects in this model, that is they have no identity and are immutable (a reader cannot edit its comment after it has been published...). All other elements are true entities. If I consider the Blog to be the root object then the relation between Blog and Person is of type many-to-one (a person can be the owner of more than one blog). On the other hand the relation between Blog and Post is of type one-to-many. The parent and the children are both entities.

A special case (as we will see) is the relation between Post and Comment (since Comment is a value object). It is also of type one-to-many but this time the parent is an entity and the children are value objects.

Mapping

How can we map this? Well, let's start with the easy one. In this simplified model the Person class has no external dependencies and is thus easy to map

public class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        Id(x => x.Id);
        Map(x => x.FirstName);
        Map(x => x.LastName);
    }
}

The Comment class has also no external dependencies. I want to treat the Comment as a value Object. So I have to map it as follows

public class PostMap : ClassMap<Post>
{
    public PostMap()
    {
        Id(x => x.Id);
        Map(x => x.Title);
        Map(x => x.Body);
        Map(x => x.PublicationDate);
        HasManyComponent<Comment>(x => x.Comments,
                                  c =>
                                      {
                                          c.Map(x => x.Text);
                                          c.Map(x => x.AuthorEmail);
                                          c.Map(x => x.CreationDate);
                                      }).AsSet();
    }
}

I had to implement the method HasManyComponent by myself since it was missing in the actual trunk of the framework. That is, it was not possible to map a collection of value objects. But it has not been that hard since the source base is really nice. My changes will probably be integrated into the framework soon. The official contributors to the project are VERY responsive and do their best to fix bugs and/or implement missing features. Keep on rolling guys! IMHO we will see soon a high adoption rate of this new framework in the NHibernate community if the development pace stay at this high rate.

I don't want to show the implementation details of the method mentioned above in this post since it is off-topic and since it will soon be incorporated into the framework anyway. Eventually the name of the method will change though...

Finally we can map the Blog class which is now easy

public class BlogMap : ClassMap<Blog>
{
    public BlogMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        References(x => x.Author);
        HasMany<Post>(x => x.Posts).AsSet();
    }
}

Note that we map the many-to-one relation between Blog and Person with the aid of the References method. Note further that we map the collection of Posts with the HasMany method. Since by default this method maps to a "bag" we have to further specify that we want to map with a "set" (--> see my post on collection mapping for the various types of collections).

The XML generated by the above mapping class is shown below. Now you can ask yourself which way of mapping your entities you prefer...

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false" 
                   assembly="FluentMapping.Domain" 
                   namespace="FluentMapping.Domain.Scenario3">
  <class name="Post" table="[Post]" xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" column="Id" type="Int64">
      <generator class="identity" />
    </id>
    <property name="PublicationDate" column="PublicationDate" type="DateTime">
      <column name="PublicationDate" />
    </property>
    <property name="Body" column="Body" length="100" type="String">
      <column name="Body" />
    </property>
    <property name="Title" column="Title" length="100" type="String">
      <column name="Title" />
    </property>
    <set name="Comments" cascade="none">
      <key column="Post_id" />
      <composite-element class="FluentMapping.Domain.Scenario3.Comment, 
                                FluentMapping.Domain, Version=1.0.0.0, 
                                Culture=neutral, PublicKeyToken=null">
        <property name="CreationDate" column="CreationDate" type="DateTime">
          <column name="CreationDate" />
        </property>
        <property name="AuthorEmail" column="AuthorEmail" length="100" type="String">
          <column name="AuthorEmail" />
        </property>
        <property name="Text" column="Text" length="100" type="String">
          <column name="Text" />
        </property>
      </composite-element>
    </set>
  </class>
</hibernate-mapping>

Ok I admit, when hand crafting the XML we can skip some of the elements, but still...

Testing

All tests use the base class FixtureBase which I have introduced in my first post about the mapping framework. In the mean time the SessionSource class of the framework has been re-factored such as that it now works for our scenarios and I don't have to use my own implementation any more. For completeness I present here the updated source once again

public class FixtureBase
{
    protected SessionSource SessionSource { get; set; }
    protected ISession Session { get; private set; }
 
    [SetUp]
    public void SetupContext()
    {
        Before_each_test();
    }
 
    [TearDown]
    public void TearDownContext()
    {
        After_each_test();
    }
 
    protected virtual void Before_each_test()
    {
        SessionSource = new SessionSource(new TestModel());
        Session = SessionSource.CreateSession();
        SessionSource.BuildSchema(Session);
        CreateInitialData(Session);
        Session.Flush();
        Session.Clear();
    }
 
    protected virtual void After_each_test()
    {
        Session.Close();
        Session.Dispose();
    }
 
    protected virtual void CreateInitialData(ISession session)
    {
    }
}

The only two lines that have changed are printed in bold.

Now let's test whether we can create a blog and add posts to it. Let's start with the former. I define a base class for all my further blog related tests as

public class Blog_Fixture : FixtureBase
{
    protected Person author;
 
    protected override void CreateInitialData(ISession session)
    {
        base.CreateInitialData(session);
        author = new Person {FirstName = "Gabriel", LastName = "Schenker"};
        session.Save(author);
    }
}

In the CreateInitialData method I create an author object since every blog has to have an author. I save this author object to the database. To make the author available to all child test classes I have declared it as a protected filed. Now to the test which tries to create a new blog and verifies that it has be written correctly and completely to the database

[TestFixture]
public class When_no_blog_exists : Blog_Fixture
{
    [Test]
    public void Can_add_new_blog()
    {
        var blog = new Blog {Name = "Gabriel's Blog", Author = author};
        Session.Save(blog);
        Session.Flush();
        Session.Clear();
 
        var fromDb = Session.Get<Blog>(blog.Id);
 
        fromDb.ShouldNotBeNull();
        fromDb.ShouldNotBeTheSameAs(blog);
        fromDb.Id.ShouldEqual(blog.Id);
        fromDb.Name.ShouldEqual(blog.Name);
        fromDb.Author.ShouldNotBeNull();
        fromDb.Author.Id.ShouldEqual(blog.Author.Id);
    }
}

Note that I have inherited this test class from the previously implemented Blog_Fixture class. In the test method I first create a new blog instance. Then I save it to the database. I then flush and clear the session instance to guarantee that all the object(s) in NHibernate's session cache are written to the DB and that the cache is cleared afterwards such as that when a read operation is invoked the respective object is really retrieved from the database.

If you wonder where all these ShouldXXX methods in the second part of the test come from then wonder no longer. These are extension methods which I have implemented. They make all the asserts that you normally would do with the aid on NUnit's Assert class. But like this the code is way more readable, isn't it? If you wonder how these methods are implemented then please have a look into the source code of the solution accompanying this post. Search for the class SpecificationExtensions.

When running this test it succeeds!

But we have seen in the past that the framework offers us some help to reduce the size of our test methods. So let's revisit the test and leverage the framework.

[Test]
public void Can_add_new_blog_revisited()
{
    new PersistenceSpecification<Blog>(Session)
        .CheckProperty(x => x.Name, "Gabriel's Blog")
        .CheckProperty(x => x.Author, author);
}
Yeah, much shorter! That's what I call wrist friendly... Of course when run also this test succeeds.

Second we want to try to add a post to an already existing blog. I have the following code for that

 
[TestFixture]
public class When_a_blog_exists : Blog_Fixture
{
    private Blog blog;
 
    protected override void CreateInitialData(ISession session)
    {
        base.CreateInitialData(session);
        blog = new Blog {Name = "Gabriel's Blog", Author = author};
        session.Save(blog);
    }
 
    [Test]
    public void Can_add_post_to_blog()
    {
        var post = new Post
                    {
                        Title = "First Post",
                        Body = "Just a test",
                        PublicationDate = DateTime.Today
                    };
        blog.Posts.Add(post);
        Session.Update(blog);
 
        Session.Flush();
        Session.Clear();
 
        var fromDb = Session.Get<Blog>(blog.Id);
 
        fromDb.Posts.Count.ShouldEqual(1);
        fromDb.Posts.First().Id.ShouldEqual(post.Id);
    }
}

In the CreateInitialData I setup my context which in this case is: I have a blog in the database. In the test method I take this existing blog instance and add a new post to it. I then tell the session to update the blog. As usual I flush and clear the session before I assert that the operation was indeed successful.

Now I reload the blog from the database and test whether it has one post as expected and whether it's the post we have added to the blog (it suffices to test the post's id). Note that the method First() applied to the Posts collection of the blog (on the last line of the test) is also an extension method. This extension method just returns the first element of any collection of objects implementing IEnumerable<T> onto which it is applied.

Again when we run the test it is successful.

We want to leverage the framework once more and thus I revisit the test

[Test]
public void Can_add_post_to_blog_revisited()
{
    var posts = new[]
                    {
                        new Post {
                                    Title = "First Post",
                                    Body = "Just a test",
                                    PublicationDate = DateTime.Today
                                 },
                        new Post {
                                    Title = "Second Post",
                                    Body = "Just another test",
                                    PublicationDate = DateTime.Today.AddDays(-1)
                                 },
                    };
 
    new PersistenceSpecification<Blog>(Session)
        .CheckProperty(x => x.Name, "Gabriel's Blog")
        .CheckProperty(x => x.Author, author)
        .CheckList(x=>x.Posts, posts);
}

Once again I use our friend the PersistenceSpecification class. This time I use it's method CheckList to test the Posts collection of the blog instance. This method expects a collection of Post objects which I have defined in the first part of this test. Here I have defined two posts in the list but also a single one would suffice for the test.

Let me resume: to completely test the mapping of the Blog class I need four lines of code! Nice.

The last thing we have left to test is whether we can add comments to our posts. First I setup my context; that is I have a blog with one post. I also prepare a comment which I can then later on add to the post.

[TestFixture]
public class When_a_blog_with_a_post_exists : Blog_Fixture
{
    private Blog blog;
    private Post post;
    private Comment comment;
 
    protected override void CreateInitialData(ISession session)
    {
        base.CreateInitialData(session);
        blog = new Blog { Name = "Gabriel's Blog", Author = author };
        post = new Post
                   {
                       Title = "First Post",
                       Body = "Just a test",
                       PublicationDate = DateTime.Today
                   };
        blog.Posts.Add(post);
        session.Save(blog);
 
        comment = new Comment("This is my comment", DateTime.Today, "someone@gmail.com");
    }
}

Once my context is set up writing the test is easy. I read the post from the database, add the prepared comment to it and then flush and clear the session (note that the session automatically realizes that the post is dirty and that an update must be made to the database). The I re-read the post from the database and verify that indeed one comment was added and that it is the comment which I expect (by comparing it's Id).

[Test]
public void Can_add_comment_to_post()
{
    var thePost = Session.Get<Post>(post.Id);
    thePost.Comments.Add(comment);
    
    Session.Flush();
    Session.Clear();
 
    var fromDb = Session.Get<Post>(post.Id);
    fromDb.Comments.Count.ShouldEqual(1);
    fromDb.Comments.First().Equals(comment);
}

And again the test succeeds. Unfortunately we cannot leverage the framework this time since the CheckList method of the PersistenceSpecification class does not yet work for collections of value objects. But I'm sure this will be fixed soon. The test would be like this

[Test][Ignore(".CheckList is not yet working")]
public void Can_add_comment_to_post_revisited()
{
    new PersistenceSpecification<Post>(Session)
        .CheckProperty(x => x.Title, "Some title")
        .CheckProperty(x => x.Body, "Some text")
        .CheckProperty(x => x.PublicationDate, DateTime.Today)
        .CheckList(x => x.Comments, new[] {comment});
}

Source Code

You can get the source code of the solution accompanying this post here.

Summary

In this post I have shown you that the mapping framework is indeed ready for mapping more advanced scenarios. I have shown you how to map one-to-many relations where either the children are entities or the children are value objects. I also have shown how to map many-to-one relations.

Published at

A fluent interface to NHibernate - Part 2 - Value Objects

In my last post I introduced a new framework which gives you the possibilities to define the mappings of the entities to the underlying database in C# using a fluent interface instead of writing XML mapping files. This has caused some discussion in the community on the pros and cons of this approach.

Let me repeat what the goals of this new framework are or should be

  • reduce friction when mapping entities (and value objects) to the underlying database
  • mapping should be more expressive than use of plain XML
  • mapping should be more testable
  • flexible, that is: allow the use of mapping conventions

How to map common scenarios

Now let's have a look at some common scenarios which you encounter daily in a moderately complex domain model. Let's concentrate on how these scenarios are mapped by using the fluent interface.

Scenario 1: Value Objects

In DDD you have the notion of entities and value objects. The latter are immutable and have no identity. In NHibernate they are mapped as Component and its fields are embedded in the same table as the containing entity.

A typical value object is Money which represents a monetary value. Let's define the following simple domain model

image

We have an account which is an entity and the account contains a property of type Money (called Balance). Balance is now a value object and contains not only the amount but also the currency in which the value is expressed (Note: 100 US$ is different than e.g. 100 €). The code for the money class

public class Money
{
    private Money()
    {
    }
 
    public Money(decimal amount, string currency)
    {
        Amount = amount;
        Currency = currency;
    }
 
    public virtual decimal Amount { get; private set; }
    public virtual string Currency { get; private set; }
}

Note that the properties are read only since any value object is immutable (once set you cannot change it). The private parameter-less constructor is there ONLY to satisfy NHibernate which needs it. But since it is private we cannot accidentally use it.

The code for the Account class is trivial

public class Account : Entity
{
    public virtual string Name { get; set; }
    public virtual Money Balance { get; set; }
}

Note that Account inherits from the Entity base class which is implemented in the framework. As discussed in my previous post I regard this as a limitation of the framework. This requirement possibly will be eliminated in future versions of the framework.

How can we map this scenario? Let's have a look at the necessary code

public class AccountMap : ClassMap<Account>
{
    public AccountMap()
    {
        Id(x => x.Id);
 
        Map(x => x.Name)
            .CanNotBeNull()
            .WithLengthOf(50);
        
        Component<Money>(x => x.Balance, m =>
                                             {
                                                 m.Map(x => x.Amount, "BalanceAmount");
                                                 m.Map(x => x.Currency, "BalanceCurrency");
                                             });
    }
}

Easy, isn't it? First we map the property Id of our account entity (inherited from the base Entity class). Then we map the Name property. We declare that it cannot be null and that it's maximal length should not exceed 50 characters.

Finally we map the Balance property which is a value object an thus treated by NHibernate as Component. Here I have used the second (optional) parameter of the map function which is the name of the table column to which the respective property should be mapped. When we create the database schema from this mapping it will contain one table called Account which contains the four columns Id, Name, BalanceAmount and BalanceCurrency.

Scenario 2: Entity with multiple properties of same value object type

How does this fit for a scenario where I have an entity which has more than one property of the same value object type? Let's have a look at the following simple model. An Employee entity has a HomeAddress and a WorkAddress field. Both fields are of type Address. Address is a value object.

image

Again the code for the Address value object (which is immutable!)

public class Address
{
    public virtual string AddressLine1 { get; private set; }
    public virtual string AddressLine2 { get; private set; }
    public virtual string PostalCode { get; private set; }
    public virtual string City { get; private set; }
    public virtual string Country { get; private set; }
 
    private Address()
    {
    }
 
    public Address(string addressLine1, string addressLine2, string postalCode, string city, string country)
    {
        AddressLine1 = addressLine1;
        AddressLine2 = addressLine2;
        PostalCode = postalCode;
        City = city;
        Country = country;
    }
}

and the Employee entity

public class Employee : Entity
{
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual Address HomeAddress { get; set; }
    public virtual Address WorkAddress { get; set; }
}

Now let's have a look at the mapping code

public class EmployeeMap : ClassMap<Employee>
{
    public EmployeeMap()
    {
        Id(x => x.Id);
        Map(x => x.FirstName).CanNotBeNull().WithLengthOf(20);
        Map(x => x.LastName).CanNotBeNull().WithLengthOf(20);
 
        Component<Address>(x => x.HomeAddress,
                           a =>
                               {
                                   a.Map(x => x.AddressLine1, "Home_AddressLine1");
                                   a.Map(x => x.AddressLine2, "Home_AddressLine2");
                                   a.Map(x => x.PostalCode, "Home_PostalCode");
                                   a.Map(x => x.City, "Home_City");
                                   a.Map(x => x.Country, "Home_Country");
                               });
 
        Component<Address>(x => x.WorkAddress,
                           a =>
                               {
                                   a.Map(x => x.AddressLine1, "Work_AddressLine1");
                                   a.Map(x => x.AddressLine2, "Work_AddressLine2");
                                   a.Map(x => x.PostalCode, "Work_PostalCode");
                                   a.Map(x => x.City, "Work_City");
                                   a.Map(x => x.Country, "Work_Country");
                               });
    }
}

Note that we have to explicitly name the underlying columns here (e.g. "Home_City" versus "Work_City") otherwise the schema generation would fail.

Honestly, I don't like the above code since it is not DRY. So let's refactor it...

public class EmployeeMap : ClassMap<Employee>
{
    private Action<ComponentPart<Address>> MapAddress(string columnPrefix)
    {
        return a =>
                   {
                       a.Map(x => x.AddressLine1, columnPrefix + "AddressLine1");
                       a.Map(x => x.AddressLine2, columnPrefix + "AddressLine2");
                       a.Map(x => x.PostalCode, columnPrefix + "PostalCode");
                       a.Map(x => x.City, columnPrefix + "City");
                       a.Map(x => x.Country, columnPrefix + "Country");
                   };
    }
 
    public EmployeeMap()
    {
        Id(x => x.Id);
        Map(x => x.FirstName).CanNotBeNull().WithLengthOf(20);
        Map(x => x.LastName).CanNotBeNull().WithLengthOf(20);
 
        Component<Address>(x => x.HomeAddress, MapAddress("Home_"));
        Component<Address>(x => x.WorkAddress, MapAddress("Work_"));
    }
}

I have extracted the mapping of the address into a helper method and can now call it as many times as I have to and just have to provide the table column prefix to be used for all fields of the address. What I still don't like in the above approach is that I need an internal helper method to map my addresses. What if I have another entity (say Customer) which also has one or several properties of type Address?

It would be nice if the framework would provide some component mapper.

Since I cannot rely on the framework at the moment I have found the following more elegant solution, where the mapping of the Address value object is externalized into it's own mapper class

public class AddressMap
{
    public static Action<ComponentPart<Address>> WithColumnPrefix(string columnPrefix)
    {
        return a =>
        {
            a.Map(x => x.AddressLine1, columnPrefix + "AddressLine1");
            a.Map(x => x.AddressLine2, columnPrefix + "AddressLine2");
            a.Map(x => x.PostalCode, columnPrefix + "PostalCode");
            a.Map(x => x.City, columnPrefix + "City");
            a.Map(x => x.Country, columnPrefix + "Country");
        };
    }
}

and then the Employee mapper class can be simplified to this

public class EmployeeMap : ClassMap<Employee>
{
    public EmployeeMap()
    {
        Id(x => x.Id);
        Map(x => x.FirstName).CanNotBeNull().WithLengthOf(20);
        Map(x => x.LastName).CanNotBeNull().WithLengthOf(20);
 
        Component(x => x.HomeAddress, AddressMap.WithColumnPrefix("Home_"));
        Component(x => x.WorkAddress, AddressMap.WithColumnPrefix("Work_"));
    }
}

Well, I'm now quite happy with my solution.

Testing the mapping

Now let's write a test for the mapping. A simple test which verifies that the mapping is correct and that a record can be written to the database is quite easy to implement

[TestFixture]
public class Employee_Fixture : FixtureBase
{
    [Test]
    public void Verify_that_employee_saves()
    {
        var emp = new Employee
                      {
                          FirstName = "Gabriel",
                          LastName = "Schenker",
                          HomeAddress = new Address("Castle home", null, "8888", "Paradise", "Switzerland"),
                          WorkAddress = new Address("My work place", null, "7777", "Atlantis", "Pegasus")
                      };
        Session.Save(emp);
 
        Session.Flush();
        Session.Clear();
 
        var fromDb = Session.Get<Employee>(emp.Id);
        Assert.AreNotSame(emp, fromDb);
        Assert.AreEqual(emp.FirstName, fromDb.FirstName);
        Assert.AreEqual(emp.LastName, fromDb.LastName);
        Assert.AreEqual(emp.HomeAddress.AddressLine1, fromDb.HomeAddress.AddressLine1);
        Assert.AreEqual(emp.HomeAddress.AddressLine2, fromDb.HomeAddress.AddressLine2);
        Assert.AreEqual(emp.HomeAddress.PostalCode, fromDb.HomeAddress.PostalCode);
        Assert.AreEqual(emp.HomeAddress.City, fromDb.HomeAddress.City);
        Assert.AreEqual(emp.HomeAddress.Country, fromDb.HomeAddress.Country);
        Assert.AreEqual(emp.WorkAddress.AddressLine1, fromDb.WorkAddress.AddressLine1);
        Assert.AreEqual(emp.WorkAddress.AddressLine2, fromDb.WorkAddress.AddressLine2);
        Assert.AreEqual(emp.WorkAddress.PostalCode, fromDb.WorkAddress.PostalCode);
        Assert.AreEqual(emp.WorkAddress.City, fromDb.WorkAddress.City);
        Assert.AreEqual(emp.WorkAddress.Country, fromDb.WorkAddress.Country);
    }
}
Note that the test fixture inherits from the FixtureBase class which I have described in my previous post. Further note that I use SqlLite as my in-memory database for testing. Let's run the test. Well, it passes as we expected.
But now let's use the framework to help reduce some code. As shown in my previous post we can use the PersistenceSpecification class of the mapping framework for this purpose. A test looks like follows
 
[Test]
public void Verify_that_employee_saves_revisited()
{
    new PersistenceSpecification<Employee>(Session)
        .CheckProperty(x=>x.FirstName, "Gabriel")
        .CheckProperty(x=>x.LastName, "Schenker")
        .CheckProperty(x => x.HomeAddress, new Address("Castle home", null, "8888", "Paradise", "Switzerland"))
        .CheckProperty(x => x.WorkAddress, new Address("My work place", null, "7777", "Atlantis", "Pegasus"))
        .VerifyTheMappings();
}
Let's run this test. Ooops, the result of the test is red! See chapter Update below!

image

The problem is that SqlLite is local to a session. That is, whenever I open a new session I have another (in-memory) database. And since the actual implementation of the PersistenceSpecification class uses a new session to test we have the problem that we now don't have access to the original schema prepared for the test.

So, what can we do? Ok, once again we have to fix the PersistenceSpecification and implement a constructor which takes an existing open session to execute the test.

The problematic code of the PersistenceSpecification class is here

image

I tried to fix it, but a quick and dirty solution didn't work. There has to be done some major re-factoring...

Update (15. Aug. 2008)

The contributors to the framework have worked hard. They changed the implementation of the PersistenceSpecification class such as that it now works also with the SqLite in-memory database. The above test is now working as it should.

Source Code

You can get the source code of the solution accompanying this post here.

Summary

In this post I discussed the mapping of complex entities having one to many properties which are value objects. I have shown that a mapping is possible with the current release of the mapping framework. The PersistenceSpecification class of the framework which should decrease the work to do for testing does not currently work with a SqlLite in-memory database. The PersistenceSpecification class of the framework which decreases the work to do for testing now works also with the SqLite in-memory database.

Enjoy

Blog Signature Gabriel .

Published at

A fluent interface to NHibernate

Do you like NHibernate? Do you like XML? My answer would be yes for the former and no for the latter. But if you want to map your entities to the underlying database tables you have no other choice than use XML. Ok, you are right, we still have the possibility to use attributes for the mapping (e.g. by using Castle Active Record) but in this case we are "polluting" our nice domain objects with infrastructure related information which definitely does NOT belong into the domain model.

Here comes our salvation. We now have a third player in the field. As first published by Jeremy D. Miller and later on by others (James Gregory, Bobby Johnson, Zachariah Young, etc. ) we can map our domain objects by using a fluent interface which solves the following possible problems

  • Changing the property names of a domain model can break the NHibernate mapping
  • Changing the database fields can break the NHibernate mappings

and has the benefit of

  • we can write the mappings in plain old C#
  • the mapping is more expressive
  • the mapping is better testable

You can download the source code for the Fluent NHibernate project from here.

Sample

Let's make a quick sample. You can download it's source here.

In our domain model we have a Product class defined as follows

public class Product
{
    public virtual long Id { get; set; }
    public virtual string Name { get; set; }
    public virtual Decimal UnitPrice { get; set; }
    public virtual int UnitsOnStock { get; set; }
    public virtual bool Discontinued { get; set; }
}

This class we can now easily map to the underlying database with this code

public class ProductMap : ClassMap<Product>
{
    public ProductMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        Map(x => x.UnitPrice);
        Map(x => x.UnitsOnStock);
        Map(x => x.Discontinued);
    }
 
}

Now let's write a quick test to see whether we can really e.g. add a new product to the underlying database. In our case the database used for tests is the SqlLite database.

Prerequisites

I have to write a helper class which will be my session source. The mapping framework already contains such a session source but its implementation does not fit my needs. Since it is not a complicate class I implement my own one. The session source class has to implement the interface ISessionSource also found in the mapping framework. Here is the code

public class MySessionSource : ISessionSource
{
    private readonly ISessionFactory _sessionFactory;
    private readonly Configuration _configuration;
 
    public MySessionSource(PersistenceModel model) : this(null, model)
    {
    }
 
    public MySessionSource(IDictionary<string, string> properties, PersistenceModel model)
    {
        if(model == null) throw new ArgumentException("Model cannot be null!");
 
        _configuration = new Configuration();
        if (properties == null)
            _configuration.Configure();
        else
            _configuration.AddProperties(properties);
 
        Model = model;
        model.Configure(_configuration);
 
        _sessionFactory = _configuration.BuildSessionFactory();
    }
 
    public PersistenceModel Model { get; private set; }
 
    public ISession CreateSession()
    {
        return _sessionFactory.OpenSession();
    }
 
    public void BuildSchema()
    {
        var session = CreateSession();
        BuildSchema(session);
    }
 
    public void BuildSchema(ISession session)
    {
        var connection = session.Connection;
 
        var drops = _configuration.GenerateDropSchemaScript(_sessionFactory.Dialect);
        executeScripts(drops, connection);
 
        var scripts = _configuration.GenerateSchemaCreationScript(_sessionFactory.Dialect);
        executeScripts(scripts, connection);
    }
 
    private static void executeScripts(string[] scripts, IDbConnection connection)
    {
        foreach (var script in scripts)
        {
            var command = connection.CreateCommand();
            command.CommandText = script;
            command.ExecuteNonQuery();
        }
    }
}

I have two overloaded constructors. I can either provide only the persistence model I use or pass the model and the necessary NHibernate configuration as dictionary of properties. In the former case the configuration is loaded from the usual hibernate.cfg.xml configuration file. The constructor then creates a new NHibernate configuration instance and uses the passed persistence model instance to feed the mapping information into the configuration instance.

The class also implements a method the create (or open) an new NHibernate session instance.

Finally we have a BuildSchema method which is overloaded. The second overload is needed when testing with SqlLite as database since when using this database in the in-memory mode (which we do in our unit tests) the database is destroyed whenever the session is closed. So, if I use a session instance to create the schema and then another for the test, then the latter does not have access to the database created by the former.

Base class for unit tests

I now write a base class for all unit test that I'll implement. This base class should be responsible for the (re-)creation of the database schema before each test runs. It should also open a new session object before each test which I can then use in my unit tests. Finally the base class should close an dispose the session after each test. Here is the code

public class FixtureBase
{
    private MySessionSource _source;
 
    protected ISession Session { get; private set; }
 
    [SetUp]
    public void SetupContext()
    {
        Before_each_test();
    }
 
    [TearDown]
    public void TearDownContext()
    {
        After_each_test();
    }
 
    protected virtual void Before_each_test()
    {
        _source = new MySessionSource(new TestModel());
        Session = _source.CreateSession();
        _source.BuildSchema(Session);
        CreateInitialData(Session);
        Session.Clear();
    }
 
    protected virtual void After_each_test()
    {
        Session.Close();
        Session.Dispose();
    }
 
    protected virtual void CreateInitialData(ISession session)
    {
    }
}

Note that the SetUp and TearDown methods just delegate to protected virtual methods Before_each_test and After_each_test respectively. The latter two methods can be overridden in any child class. In the Before_each_test method I use the session source class to a) create a new session instance and b) (re-)build the database schema. A call to the virtual method CreateInitialData is executed and then the session is cleared. The CreateInitialData method can be used in the child classes to setup the respective context for the unit tests.

The After_each_test method just closes and disposes the session.

The first unit test

Finally we can write our first test and verify whether the mapping with the fluent interface really works. First we want to try to add a new Product to the database. With all the prerequisites in place this is now easy. See the code below

[TestFixture]
public class Product_Fixture : FixtureBase
{
    [Test]
    public void Can_add_product_to_database()
    {
        var product = new Product
                          {
                              Name = "Apple",
                              UnitPrice = 0.25m,
                              UnitsOnStock = 1255,
                              Discontinued = false
                          };
        Session.Save(product);
 
        // Assertion
        Session.Flush();
        Session.Clear();
        var fromDb = Session.Get<Product>(product.Id);
        Assert.AreNotSame(product, fromDb);
        Assert.AreEqual(product.Name, fromDb.Name);
        Assert.AreEqual(product.UnitPrice, fromDb.UnitPrice);
        Assert.AreEqual(product.UnitsOnStock, fromDb.UnitsOnStock);
        Assert.AreEqual(product.Discontinued, fromDb.Discontinued);
    }
}
We define a new test class which inherits from our base class FixtureBase. The we define the test which creates a new instance of type Product and populates the various properties with sample data. We then call the Save method of the session and pass the product as a parameter.

Then we flush and clear the session and reload the Product from database. We assert that it has really been loaded from the database and not just taken out of NHibernate's first level cache (to avoid that we have flushed and cleared the session). Then we assert that the values of the properties all match.

Unit test revisited

If we have a lot of entities then we potentially have lot's of repetitive code to implement just to unit test all of our entities as above. Hey but wait a minute. There is a "better" way provided by the mapping framework. We can use the PersistenceSpecification class to eliminate the repetitive work. Let's look how our code will be

[Test]
public void Can_add_product_to_database_revisited()
{
    new PersistenceSpecification<Product>(SessionSource)
        .CheckProperty(x=>x.Name, "Apple")
        .CheckProperty(x=>x.UnitPrice, 0.25m)
        .CheckProperty(x=>x.UnitsOnStock, 2345)
        .CheckProperty(x=>x.Discontinued, true);
}

That's a nice reduction in lines of code. No "noise" any more, just the essential is left.

Note: Unfortunately this second approach has a side effect which in my opinion is not nice! The entity must inherit from the base class Entity provided by the mapping framework. This introduces a dependency in the domain model (the domain model must reference the mapping framework) and also is against the principle of POCO (plain old C# object). Maybe I want to provide a different entity base class. Well there is some room for improvement left...

Summary

If you want a clean domain model free from pollution by mapping attributes you had to define the mapping between entities and the underlying database with XML documents. XML is not very wrist friendly and also not very readable. Now there is a third alternative to define the mapping of entities to database - the fluent NHibernate API. One can now define the mapping in C# with a nice and very readable code.

As always you can download the code for the sample here.

Enjoy

Blog Signature Gabriel .

Published at

Database Migration

In my last post I discussed the automated management of an SQL server database. In the post I used the Tarantino database migration tool.

Ben Scheirman recently has written an excellent post about some other tools that are also available for doing the job.

Where the Tarantino migration tool uses TSQL scripts to do the migrations most of the other tools define the DDL in C# or Ruby.

For reference I put here the list of tools mentioned in Ben's post

Enjoy

Blog Signature Gabriel .

Published at

Manage SQL Databases

Note: the following article is only targeting Microsoft SQL Server (I regret...).

In a previous article I have discussed the schema generation and schema update offered by NHibernate. In this post I want to discuss a way how you can generate and/or maintain your SQL Server database.

When practicing agile development one of the most important cornerstones of this methodology is implementing continuous integration (CI). That is any solution your team develops should be able to build in fully automated manner. One of the build steps is of course the creation and or update of the database and the database schema.

Tools to automate the build process

Many people use either nant or msbuild to fully automate their build. And when I say build it includes the following tasks(others are possible)

  • versioning/tagging the sources
  • compiling the sources (in Visual Studio called build)
  • running unit tests, integration tests, acceptance tests, stress tests
  • dropping and re-creating the database
  • re-creating the database schema
  • creating a package
  • if Web: deploy the web site
  • if Other: create installer

In this post I'll discuss the two tasks marked in blue.

The nant task

There is an OSS project on Google Code which is dedicated to the change management of SQL server databases. It's called Tarantino and can be found here. One of the outcome of this project is a custom nant task called manageSqlDatabase. We will use nant and this custom task to manage our (sample) database.

You need the following files to be able to use the custom task

To get the files for your own solution either download the sample solution accompanying this post or download it directly from the Tarantino project which you can find here.

The build file

The general format of the custom nant task is

<manageSqlDatabase
  scriptDirectory="${database.script.directory}"
  action="${action}"
  server="${database.server}"
  integratedAuthentication="${database.integrated}"
  database="${database.name}"
  username="${database.username}"
  password="${database.password}"
/>

The sriptDirectory contains the path to the files which contain the schema creation and/or schema update statements.

The possible actions are

  • dropDatabase
  • createDatabase
  • rebuildDatabase
  • updateDatabase

The server parameter must contain the name of the SQL Server (e.g. "localhost/SQLEXPRESS").

The parameter IntegratedAuthentication can be either true or false.

The parameter database contais the name of the database to re-create or update (e.g. "SampleDatabase")

The parameters username and password are only needed if IntegratedAuthentication is set to false.

A typical create database scenario could be as shown below

<manageSqlDatabase
  scriptDirectory="src\database"
  action="createDatabase"
  server="localhost"
  integratedAuthentication="true"
  database="SampleDatabase"
/>

Let's not construct a complete build file for nant which includes the task of dropping and re-creating a database and the creation of the database schema. We create a new empty file called default.build and enter the following XML fragments.

<?xml version="1.0" encoding="utf-8"?>
<project name="DemoSolution" default="builddatabase" 
         xmlns="http://nant.sf.net/release/0.85/nant.xsd">
    <property name="solution.dir" value="src" />
    <property name="database.script.directory" value="${solution.dir}/Database"/>
    <property name="database.server" value="localhost"/>
    <property name="database.name" value="${project::get-name()}"/>
 
    <target name="builddatabase" depends="dropDatabase, createDatabase" />
    
    <target name="dropDatabase">
  </target>
    
    <target name="createDatabase">
  </target>
  
</project>

In this file we define a new nant project called DemoSolution. The default target that is executed is builddatabase. Then we define some properties for reference in our project (if you are not fluent in nant syntax please consult the online documentation here.)

The builddatabase target does nothing else than trigger the targets dropDatabase and createDatabase, that is if the database already exists then it is dropped and then re-created. Finally the database schema is created. But wait, those two targets are empty at the moment and will do absolutely nothing at the moment.

Let's now add this helper target to the build file - we want to avoid duplication don't we?

<target name="manageSqlDatabase">
  <manageSqlDatabase
    scriptDirectory="${database.script.directory}"
    action="${action}"
    server="${database.server}"
    integratedAuthentication="true"
    database="${database.name}"
  />
 
  <if test="${action != 'Drop'}">
    <echo message="Current Database Version: ${usdDatabaseVersion}" />
  </if>
 
</target>

it will be called by the dropDatabase and createDatabase targets where each provides another action parameter. Note that the usdDatabaseVersion parameter is generated by the manageSqlDatabase custom task.

Now we complete the dropDatabase and createDatabase targets as follows

<target name="dropDatabase">
  <property name="action" value="Drop" />
  <call target="manageSqlDatabase" failonerror="false"/>
</target>
 
<target name="createDatabase">
  <property name="action" value="Create" />
  <call target="manageSqlDatabase" />
</target>

that is we use the standard call task of nunit to trigger the custom task. Note that the dropDatabase target calls the custom task with failonerror set to false (default is true). It is possible that the database does not yet exist. In this case the build should just continue.

The script files

One of the main parts in the automation process is still missing. It's the SQL script files which generate and/or update the database schema. These files have to be valid SQL scripts (you should be able to run these scripts without errors in e.g. a query session in "SQL Server Management Studio"). The scripts can contain DDL and DML statements. They have to be sequentially numbered, e.g.

  • 0001_CreateBaseSchema.sql
  • 0002_AddProductAndCategory.sql
  • 0003_AddIndexes.sql
  • 0004_InitialDataLoad.sql
  • etc.

You can freely choose any name after the underscore. The manageSqlDatabase nant task will apply the scripts sequentially starting with the lowest number and ending with the highest number. When creating the database the manageSqlDatabase nant task will add a special table to the database which keeps track of which scripts have been applied.

How to create the script files

The initial schema generation script I normally generate by using NHibernate's schema export utility. See this post for an in depth discussion. Alternatively you can also use the script database objects task of "SQL Server Management Studio". For any further modifications of the schema (especially if the first version is already in production) I use a product like Redgate's SQL Compare or the same product from Apex to generate the alter scripts.

Execute the build

We can now execute the build by invoking the following command

bin\nant\nant.exe -buildfile:default.build

we can write a batch file builddatabase.bat to further automate the process. The content of the batch file might be as follows

bin\nant\nant.exe -buildfile:default.build
pause

Sample Code

You can download a little sample from here. You need to have an SQL Server available. A local installation of SQL Server Express Edition is enough. Please adjust the properties database.server and database.name in the file default.build according your needs. Double click the file builddatabase.bat to test the creation of the database and the database schema.

Enjoy!

Blog Signature Gabriel

Published at

How to configure Log4Net for use with NHibernate

Recently there was a question in the NHUser group about how to configure Log4Net to log the queries generated by NHibernate. First of all: you can get Log4Net here. There you also find the documentation. If you are not sure about details of the configuration shown below please refer to this documentation.

Running without Log4Net

If you only want NHibernate to log the queries it sends to the data source when running unit tests you don't have to configure Log4Net at all. It suffices to add the show_sql key to the NHibernate configuration. If you are using a separate xml file to configure NHibernate (e.g. the hibernate.cfg.xml) then its content might look similar to the one below

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
    <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    <property name="connection.connection_string">Server=(local);Database=NHibernateFAQ;Integrated Security=SSPI;</property>
    
    <property name="show_sql">true</property>
  </session-factory>
</hibernate-configuration>

Now when running any unit test that involves NHibernate the queries generated by NHibernate will be logged in the output window (be it the unit test runner of Resharper or be it the Output Window of Visual Studio when you use TestDriven).

Logging with Log4Net

If you want to use Log4Net to collect logging information generated by NHibernate you have to add the necessary configuration to the config file of your application. If you want to log to two different targets (e.g. to the console and to a file) the relevant sections in your config file might look like follows

<configuration>
  ...
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  </configSections>
  
  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender, log4net">
      <layout type="log4net.Layout.PatternLayout, log4net">
        <param name="ConversionPattern" value="%d %p %m%n" />
      </layout>
    </appender>
 
    <appender name="RollingFile" type="log4net.Appender.RollingFileAppender,log4net" >
      <param name="File" value="log.txt" />
      <param name="AppendToFile" value="true" />
      <param name="DatePattern" value="yyyy.MM.dd" />
 
      <layout type="log4net.Layout.PatternLayout,log4net">
        <conversionPattern value="%d %p %m%n" />
      </layout>
    </appender>
    
    <root>
      <priority value="DEBUG" />
      <appender-ref ref="ConsoleAppender" />
    </root>
    ...
</configuration>

Here I define that all output with a priority of at least DEBUG goes to the console.

Now I have to tell my application that I want to use Log4Net. I can do that with an assembly level attribute. That is, you have to put the following code snippet somewhere in your application (e.g. the "Global. asax" if you are building a web application)

// Configure log4net using the .config file
[assembly: log4net.Config.XmlConfigurator(Watch = true)]

having done do we can now run a first unit test that accesses the database via NHibernate. The output generated by Log4Net in the unit test runner is similar to this

2008-07-02 08:40:07,249 INFO NHibernate 2.0.0.1001 (2.0.0.1001)
2008-07-02 08:40:07,251 INFO hibernate-configuration section not found in application configuration file
2008-07-02 08:40:07,254 INFO Bytecode provider name : lcg
2008-07-02 08:40:07,257 INFO Using reflection optimizer
2008-07-02 08:40:08,515 DEBUG connection.provider=NHibernate.Connection.DriverConnectionProvider
2008-07-02 08:40:08,516 DEBUG dialect=NHibernate.Dialect.MsSql2005Dialect
2008-07-02 08:40:08,517 DEBUG connection.driver_class=NHibernate.Driver.SqlClientDriver
2008-07-02 08:40:08,517 DEBUG connection.connection_string=Server=(local);Database=NHibernateFAQ;Integrated Security=SSPI;
2008-07-02 08:40:08,518 DEBUG show_sql=false
2008-07-02 08:40:08,522 DEBUG properties: System.Collections.Generic.Dictionary`2[System.String,System.String]
2008-07-02 08:40:08,526 INFO Mapping resource: LoggingSample.Person.hbm.xml
2008-07-02 08:40:08,872 INFO Using dialect: NHibernate.Dialect.MsSql2005Dialect
2008-07-02 08:40:11,425 INFO Mapping class: LoggingSample.Person -> Person
2008-07-02 08:40:11,537 DEBUG Mapped property: Id -> Id, type: Int32
2008-07-02 08:40:11,612 DEBUG Mapped property: LastName -> LastName, type: String
2008-07-02 08:40:11,614 DEBUG Mapped property: FirstName -> FirstName, type: String
2008-07-02 08:40:11,614 DEBUG Mapped property: Birthdate -> Birthdate, type: DateTime
2008-07-02 08:40:11,632 INFO checking mappings queue
2008-07-02 08:40:11,634 INFO processing one-to-many association mappings
2008-07-02 08:40:11,634 INFO processing one-to-one association property references
2008-07-02 08:40:11,634 INFO processing foreign key constraints
2008-07-02 08:40:11,712 INFO Using dialect: NHibernate.Dialect.MsSql2005Dialect
2008-07-02 08:40:11,716 INFO Using dialect defined converter
...
2008-07-02 08:40:12,410 DEBUG Static SQL for entity: LoggingSample.Person
2008-07-02 08:40:12,411 DEBUG  Version select: SELECT Id FROM Person WHERE Id = ?
2008-07-02 08:40:12,412 DEBUG  Snapshot select: SELECT person_.Id, person_.LastName as LastName0_, person_.FirstName as FirstName0_, person_.Birthdate as Birthdate0_ FROM Person person_ WHERE person_.Id=?
...

as you can see LOADS of information.

To tune the generated logging information a little bit we can filter the output generated by NHibernate by putting the following configuration section into our config file (put them just after the root section inside the log4net node)

<logger name="NHibernate" additivity="false">
  <level value="WARN"/>      
  <appender-ref ref="RollingFile" />
  <appender-ref ref="ConsoleAppender" />
</logger>
 
<logger name="NHibernate.SQL" additivity="false">
  <level value="ALL"/>      
  <appender-ref ref="RollingFile" />
  <appender-ref ref="ConsoleAppender" />
</logger>

Obviously NHibernate defines two different loggers NHibernate and NHibernate.SQL. The first one receives all logging output that NHibernate generates where as the second one only receives the sql statements generated by NHibernate.

With the above settings in place the output generated is reduced to

2008-07-02 08:48:58,636 DEBUG select person0_.Id as Id0_, 
                        person0_.LastName as LastName0_, 
                        person0_.FirstName as FirstName0_, 
                        person0_.Birthdate as Birthdate0_ 
                        from Person person0_

That's what we want. Only if we have some weird problems we need to change the priority level of the NHibernate filter to say INFO or DEBUG.

As usual you can find a demo solution here.

Enjoy

Blog Signature Gabriel .

Published at

Summer of NHibernate - Screen cast series

Stephen Bohlen has just started to publish a series of screen casts about NHibernate. Here are the links of the topics covered so far

enjoy

[updated, June 27 2008]

third part is now available at

Published at

Mapping Collections in NHibernate (Part 1)

Sorry, have been quiet for some time due to too much project work... But now lets discuss a fairly important and often misunderstood topic: the mapping of collections in NHibernate

Monitoring the NHUsers Google group I can see a lot of questions around collections and how to best map them in NHibernate. NHibernate offers several possibilities to map a collection of objects. You can use a Set, a Map, a Bag, an IdBag or a List. Let's first analyze what the ("exact" mathematical) definition of each of them is.

Theoretical background

  • A Set is a collection of distinct objects considered as a whole.
    A valid example of a set (of letters) is: { a, b, c, d }. Each letter occurs exactly once.
  • A Bag is a generalization of a set. A member of a bag can have more than one membership while each member of a set has only one membership.
    A valid example of a bag is { a, a, a, b, c, c, d, ...}. The letters a and c appear more than once in the Bag.
  • A Map (also called associative container, hash, dictionary, lookup table) is a abstract data type composed of a collection of keys and a collection of values, where each key is associated with one value. The relationship between a key and its value is sometimes called a mapping or binding.
    A valid sample would be a map of capitals of the world's countries where the country code is the key and the name of the capital is the value, i.e. { { "CH", "Bern" }, { "D", "Berlin" }, { "USA", "Washington" }, ...}
  • A List is collection of objects (also called elements or members). Each element in the List has an index. Similar to a Bag a member of the the list can have more than one membership.
    A valid sample of a list is e.g. { {1, "Bob"}, {2,"Sue"}, {3,"Ann"}, {4,"Sue"}, ...}. Obviously the name "Ann" occurs twice, once with the index 2 and once with the index 4.

.NET and the CLR

The CLR of .NET only provides us Maps and Lists. Maps are either implemented as Hashtables (non generic) or Dictionaries (generic). Lists are available as ArrayList (non generic) or List<T> (generic). But we have no direct representation of Set and Bag in the CLR. A Bag can easily be simulated by using a List. We just have the superfluous index. It is not obvious why Microsoft didn't implement a Set though. Since NHibernate makes heavy use of sets they provide an implementation of Sets in the so called IESI collection library which is part of the stack.

Samples

The code to this samples can be downloaded from here.

Collection of values

Let's take a simple sample. A customer provides several possibilities to contact him (e.g. Mobile, Office phone, EMail, FAX, etc.). We can represent this list of possible contacts as a Collection of strings.

image

Obviously we want each contact to be unique. Thus a Set would certainly be a good choice for our Contacts collection. The corresponding code is

using Iesi.Collections.Generic;
 
namespace CollectionMapping
{
    public class Customer
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual ISet<string> Contacts { get; set; }
 
        public Customer()
        {
            Contacts = new HashedSet<string>();
        }
    }
}

Note the import of the Iesi.Collections.Generic namespace which is implemented in the Iesi.Collections assembly which is part of the NHibernate stack. Note also that in the constructor we initialize the collection. A possible implementation for the ISet interface is the HashedSet<T> also found in the IESI collection library.

Let's have a look at the NHibernate mapping now

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="CollectionMapping"
                   namespace="CollectionMapping">
  <class name="Customer">
    <id name="Id">
      <generator class="native"/>
    </id>
    <property name="Name"/>
    
    <set name="Contacts">
      <key column="CustomerId" foreign-key="fk_Contact_Customer"/>
      <element column="Description" type="String"/>
    </set>
    
  </class>
</hibernate-mapping>

The schema generation script produced by the SchemaExport service of NHibernate is then (for SQL Server 2005)

create table Customer (Id INT IDENTITY NOT NULL, Name NVARCHAR(255) null, primary key (Id))
 
create table Contacts (CustomerId INT not null, Description NVARCHAR(255) null)
 
alter table Contacts add constraint fk_Contact_Customer foreign key (CustomerId) references Customer

(For a detailed discussion of Schema Generation see this post.)

Now we can write a unit test to verify we can indeed create customer objects with contacts

[Test]
public void Can_create_customer_with_contacts()
{
    var customer = new Customer {Name = "John Doe"};
    customer.Contacts.Add("Business phone: 123-12 34 56");
    customer.Contacts.Add("Mobile: 555-72 44 55");
    customer.Contacts.Add("Email: john.doe@somecompany.com");
 
    Session.Save(customer);
    Session.Flush();
    Session.Clear();
 
    // Assertions
    var fromDb = Session.Get<Customer>(customer.Id);
    Assert.AreNotSame(customer, fromDb);
    Assert.AreEqual(customer.Name, fromDb.Name);
    Assert.AreEqual(customer.Contacts.Count, fromDb.Contacts.Count);
}

which will produce the following sql commands (note: I'm using SQL Light here as my in memory test database. A detailed discussion about setting up an environment for TDD can be found in this post.)

NHibernate: INSERT INTO Customer (Name) VALUES (@p0); select SCOPE_IDENTITY(); 
@p0 = 'John Doe'
NHibernate: INSERT INTO Contacts (CustomerId, Description) VALUES (@p0, @p1); 
@p0 = '1', @p1 = 'Business phone: 123-12 34 56'
NHibernate: INSERT INTO Contacts (CustomerId, Description) VALUES (@p0, @p1); 
@p0 = '1', @p1 = 'Mobile: 555-72 44 55'
NHibernate: INSERT INTO Contacts (CustomerId, Description) VALUES (@p0, @p1); 
@p0 = '1', @p1 = 'Email: john.doe@somecompany.com'
NHibernate: SELECT customer0_.Id as Id0_0_, customer0_.Name as Name0_0_ 
FROM Customer customer0_ WHERE customer0_.Id=@p0; @p0 = '1'
 
NHibernate: SELECT contacts0_.CustomerId as CustomerId0_, 
contacts0_.Description as Descript2_0_ 
FROM Contacts contacts0_ 
WHERE contacts0_.CustomerId=@p0; @p0 = '1'

So far so good. We have a solution where each customer object has a collection of unique contacts. The contacts are just a collection of strings. Now maybe we want a contact to be a complex object with several properties instead of only a simple string.

Collection of (complex) objects

Let's assume our contact should contain a type and a description property. And let's call the collection of contacts "BusinessContacts".

 

image

 

We can define our customer and contact classes as follows

using Iesi.Collections.Generic;
 
namespace CollectionMapping
{
    public class Customer
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual ISet<Contact> BusinessContacts { get; set; }
 
        public Customer()
        {
            BusinessContacts = new HashedSet<Contact>();
        }
    }
 
    public class Contact
    {
        public virtual ContactTypes Type { get; set; }
        public virtual string Description { get; set; }
    }
 
    public enum ContactTypes
    {
        Undefined=0,
        Email,
        Phone,
        Mobile,
        Fax
    }
}
Note that the Contacts are still treated as value objects (in a DDD sense) and not entities. Thus a contact does not have an ID.

Equality and uniqueness

Now we are sure that each distinct contact can only be added to the Contacts collection once. So trying to (accidentally) add the work phone twice would result in a exception. But wait a moment! How does the Set know that two instances of type Contact are the same? Now, what does equality mean? The (online) help of Microsoft tells us that:

"In C#, there are two different kinds of equality: reference equality and value equality. Value equality is the generally understood meaning of equality: it means that two objects contain the same values. For example, two integers with the value of 2 have value equality. Reference equality means that there are not two objects to compare. Instead, there are two object references and both of them refer to the same object."

And then they add:

"Because Equals is a virtual method, any class can override its implementation. Any class that represents a value, essentially any value type, or a set of values as a group, such as a complex number class, should override Equals."

Well, internally the Set uses value equality (that is the Equals function) to differentiate objects. In our case we want to say that two (different) instances of type Contact are equal if their property Description and Type contain the same values. Thus we have to override the Equals function and provide our own implementation. But when overriding the Equals function one also has to override the GetHashCode function at the same time!

Since the type System.String and System.Int32 (an enum is by default a System.Int32) already provide an Equals and a GetHashCode implementation we take this one and thus the code to add to our Contacts class is fairly simple

public override bool Equals(object obj)
{
    if(obj == null || !(obj is Contact)) return false;
    var contact = (Contact)obj;
    return ((Description == null && contact.Description == null) || 
        Description.Equals(contact.Description)) && Type.Equals(contact.Type);
}
 
public override int GetHashCode()
{
    return string.Format("{0}|{1}", Type, Description).GetHashCode();
}
Note that to get the hash code we first convert the two properties into a unique string and then take it's default GetHashCode implementation. This might not be the most efficient solution but it certainly gives me the correct results.

Having done so we can be sure that any distinct contact is never added more than once to the Contacts collection of the Customer object.

Now let's have a look at the mapping of the classes

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="CollectionMapping"
                   namespace="CollectionMapping">
  <class name="Customer">
    <id name="Id">
      <generator class="native"/>
    </id>
    <property name="Name"/>
 
    <set name="BusinessContacts" table="BusinessContact">
      <key column="CustomerId" foreign-key="fk_BusinessContact_Customer"/>
      <composite-element class="Contact">
        <property name="Type" not-null="true"/>
        <property name="Description" not-null="true"/>
      </composite-element>
    </set>
    
  </class>
</hibernate-mapping>

Now we have a <composite-element> instead of just an <element> in the mapping file. The <composite-element> can contain as many <property> child nodes as needed.

The schema generation script produced by the SchemaExport service of NHibernate is then (for SQL Server 2005)

create table Customer (Id INT IDENTITY NOT NULL, Name NVARCHAR(255) null, primary key (Id))
create table BusinessContact (CustomerId INT not null, Type INT null, Description NVARCHAR(255) null)
alter table BusinessContact add constraint fk_BusinessContact_Customer foreign key (CustomerId) references Customer

Again we can write a unit test to verify we can indeed create customer objects with business contacts

[Test]
public void Can_create_customer_with_business_contacts()
{
    var customer = new Customer {Name = "John Doe"};
    customer.BusinessContacts.Add(new Contact
                                      {
                                          Type = ContactTypes.Phone,
                                          Description = "123-12 34 56"
                                      });
    customer.BusinessContacts.Add(new Contact
                                      {
                                          Type = ContactTypes.Mobile,
                                          Description = "555-72 44 55"
                                      });
    customer.BusinessContacts.Add(new Contact
                                      {
                                          Type = ContactTypes.Email,
                                          Description = "john.doe@somecompany.com"
                                      });
 
    Session.Save(customer);
    Session.Flush();
    Session.Clear();
 
    // Assertions
    var fromDb = Session.Get<Customer>(customer.Id);
    Assert.AreNotSame(customer, fromDb);
    Assert.AreEqual(customer.Name, fromDb.Name);
    Assert.AreEqual(customer.BusinessContacts.Count, fromDb.BusinessContacts.Count);
}

and NHibernate will produce the following output (for an SQL light database)

NHibernate: INSERT INTO Customer (Name) VALUES (@p0); select SCOPE_IDENTITY(); @p0 = 'John Doe'
NHibernate: INSERT INTO BusinessContact (CustomerId, Type, Description) VALUES (@p0, @p1, @p2); @p0 = '1', @p1 = 'Phone', @p2 = '123-12 34 56'
NHibernate: INSERT INTO BusinessContact (CustomerId, Type, Description) VALUES (@p0, @p1, @p2); @p0 = '1', @p1 = 'Mobile', @p2 = '555-72 44 55'
NHibernate: INSERT INTO BusinessContact (CustomerId, Type, Description) VALUES (@p0, @p1, @p2); @p0 = '1', @p1 = 'Email', @p2 = 'john.doe@somecompany.com'
 
NHibernate: SELECT customer0_.Id as Id0_0_, customer0_.Name as Name0_0_ 
FROM Customer customer0_ WHERE customer0_.Id=@p0; @p0 = '1'
NHibernate: SELECT businessco0_.CustomerId as CustomerId0_, businessco0_.Type as Type0_, businessco0_.Description as Descript3_0_ 
FROM BusinessContact businessco0_ WHERE businessco0_.CustomerId=@p0; @p0 = '1'

That's it for the moment. In my next post I'll discuss the Bag and the Map type of collections.

You can find the code for these samples here.

Enjoy!

Blog Signature Gabriel .

Published at

How to map a tree in NHibernate

Introduction

Lately there have been many questions regarding how to best map a tree structure in NHibernate. In this post I'll try to show you various techniques how one can deal with a tree structure.

The code for this sample you can get from here.

Domain Model

Let's define a very simple domain model for this sample. We have a single class called Equipment that has a parent of type Equipment and 0 to many children of type Equipment. The tree has a single root node. The root node is specific by the fact that it's property Parent is equal to null. On the other hand a tree has leaf nodes. A leaf node is defined to have no children.

You could as well replace the class Equipment by e.g. a Person class. The principles shown here would not change.

image

Where is my Aggregate?

A Aggregate in DDD is defined as "A cluster of associated objects that are treated as a unit for the purpose of data changes. External references are restricted to one member of the Aggregate, designated as the root. A set of consistency rules applies within the Aggregate's boundaries."

Depending on our Use Cases or User Stories we can define our Aggregate either as

image

that is, the aggregate includes the equipment (which is the root) and its children.

Or we could define the Aggregate as follows

image

here only the equipment object is part of the aggregate (it is at the same time the root of the aggregate).

In the following I choose the former aggregate (equipment and children). This corresponds to the use case where I want to edit an equipment and its children in a single business transaction.

Note: Normally one defines a Repository for each Aggregate in the domain model.

Mapping

Let's have a look at the mapping for the Equipment class.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="TreeStructure"
                   namespace="TreeStructure">
  <class name="Equipment">
    <id name="Id">
      <generator class="guid"/>
    </id>
    <property name="Name" length="50" not-null="true" unique="true"/>
    
    <many-to-one name="Parent" class="Equipment" column="ParentId" />
    
    <set name="Children" cascade="all-delete-orphan" >
      <key column="ParentId" foreign-key="fk_Equipment_ParentEquipment"/>
      <one-to-many class="Equipment"/>
    </set>
  </class>
</hibernate-mapping>

The name property of the equipment must be defined and unique. The name can be at most 50 characters long.

The parent property is not mandatory (this is the default, i.e. not_null=false) since the root node has Parent equal to null.

I have defined the children collection as a Set, that is an unordered collection of unique objects.  I have chosen cascade="all-delete-orphan" to instruct NHibernate that he automatically saves, updates or deletes the children of an equipment too when I save, update or delete the equipment. I also have defined that the foreign key constraint that will be defined on the database between the equipment and its parent has a friendly name (fk_Equipment_EquipmentParent).

Now I can write a unit test to check whether NHibernate can create the correct schema for me. In this sample I use a SQL Server 2005 database (the express edition is ok too) since later on I want to show some specific features only available in SQL Server. The code of the test is

[Test]
public void Can_generate_schema()
{
    var configuration = new Configuration();
    configuration.Configure();
    configuration.AddAssembly(typeof (Equipment).Assembly);
 
    // show the schema for debugging purposes
    new SchemaExport(configuration).Execute(true, false, false, false);
 
    // generate the schema in the database
    new SchemaExport(configuration).Execute(false, true, false, false);
}

This test runs successfully and generates the following output (SQL script)

if exists (select 1 from sys.objects 
           where object_id = OBJECT_ID(N'[fk_Equipment_ParentEquipment]') 
           AND parent_object_id = OBJECT_ID('Equipment'))
  alter table Equipment  drop constraint fk_Equipment_ParentEquipment
 
if exists (select * from dbo.sysobjects 
           where id = object_id(N'Equipment') 
           and OBJECTPROPERTY(id, N'IsUserTable') = 1) 
  drop table Equipment
 
create table Equipment (
  Id UNIQUEIDENTIFIER not null, 
  Name NVARCHAR(50) not null unique, 
  ParentId UNIQUEIDENTIFIER null, 
  primary key (Id)
)
 
alter table Equipment 
add constraint fk_Equipment_ParentEquipment 
foreign key (ParentId) references Equipment
The first part of the script drops the database objects if they are already there and in the second part of the script the table Equipment is generated as well as the foreign key constraint between the equipment and its parent. The create script for the table looks exactly like expected.

The Repository

A Repository is defined as "a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects."

As said above, for each Aggregate in the domain model one defines a Repository. Since we only have one aggregate in our simple domain we also will have only one repository. Let us call it EquipmentRepository.

Now I want to be able to eager load the complete aggregate given the id of the aggregate root. I write the following unit test

[Test]
public void Can_load_aggregate_by_id()
{
    var equipmentId = ...;    // some id
    var equipment = _repository.GetAggregateById(equipmentId);
    Assert.IsNotNull(equipment);
    Assert.IsTrue(NHibernateUtil.IsInitialized(equipment.Parent));
    Assert.IsTrue(NHibernateUtil.IsInitialized(equipment.Children));
    Assert.AreEqual(3, equipment.Children.Count);
}

With this test I assert that a) I get an aggregate and b) the aggregate is fully populated. To check whether the aggregate is fully populated I use the NHibernateUtil utility class. The test assumes the existence of a equipment tree fragment in the database. Please refer to the project (here) for any details how I create this tree fragment in the SetUp of the test fixture.

A possibility to eager load an aggregate is by using a HQL query as below

public Equipment GetAggregateById(Guid equipmentId)
{
    using (var session = SessionManager.OpenSession())
    {
        var sql = "from Equipment e" +
                  " left join fetch e.Parent p" +
                  " left join fetch e.Children c" +
                  " where e.Id = :id";
        var equipment = session.CreateQuery(sql)
            .SetGuid("id", equipmentId)
            .UniqueResult<Equipment>();
        return equipment;
    }
}

I use left joins since either Parent can be null or the equipment has no children. The SessionManager class is a helper class which I use to provide me session objects. Please have a look at the project which you can find here for any details.

Finding the root aggregate is easy. We just have to look for an equipment whose parent is equal to null

public Equipment GetRootAggregate()
{
    using (var session = SessionManager.OpenSession())
    {
        var sql = "from Equipment e" +
                  " left join fetch e.Children c" +
                  " where e.Parent is null";
        var equipment = session.CreateQuery(sql)
            .UniqueResult<Equipment>();
        return equipment;
    }
}

Now some times we want to find all leaf nodes of the tree. Remember that a leaf node has by definition no children. We could use the following code for this

public ICollection<Equipment> GetAllLeafNodes()
{
    using (var session = SessionManager.OpenSession())
    {
        var sql = "from Equipment e" +
                  " left join fetch e.Parent p" +
                  " where e.Children.size = 0";
        var leafs = session.CreateQuery(sql)
            .List<Equipment>();
        return leafs;
    }
}

here we use the handy size function for collections provided by HQL. Note that this method delivers all leaf nodes of the tree. To only select the leaf nodes of a sub-tree starting at a given equipment node is trivial now and I leave for you as an exercise.

Eager load ancestors and descendants

To eager load all ancestors or descendants of a given equipment node we have to use native TSQL since HQL (as well as the criteria API) does not provide a generic way of doing it. Fortunately SQL server 2005 provides us the means to achieve the desired result. We have to construct a hierarchical query as below

public ICollection<Equipment> GetAllDescendantsOfEquipment(Guid equipmentId)
{
    using (var session = SessionManager.OpenSession())
    {
        var sql = "with Hierachy(Id, Name, ParentId, Level)" +
                  " as" +
                  " (" +
                  "   select Id, Name, ParentId, 0 as Level" +
                  "   from Equipment e" +
                  "   where e.Id = :id" +
                  "  union all" +
                  "   select e.Id, e.Name, e.ParentId, eh.Level + 1" +
                  "   from Equipment e" +
                  "   inner join Hierachy eh" +
                  "      on e.ParentId = eh.Id" +
                  " )" +
                  " select Id, Name, ParentId" +
                  " from Hierachy" +
                  " where Level > 0";
        var list = session.CreateSQLQuery(sql)
            .AddEntity(typeof(Equipment))
            .SetGuid("id", equipmentId)
            .List<Equipment>();
        return list;
    }
}

The last where statement in the SQL assures that the given equipment is not included in the list of descendants.

Analogous we can get the list of ancestors of a given equipment node

public ICollection<Equipment> GetAllAncestorsOfEquipment(Guid equipmentId)
{
    using (var session = SessionManager.OpenSession())
    {
        var sql = "with Hierachy(Id, Name, ParentId, Level)" +
                  " as" +
                  " (" +
                  "   select Id, Name, ParentId, 0 as Level" +
                  "   from Equipment e" +
                  "   where e.Id = :id" +
                  "  union all" +
                  "   select e.Id, e.Name, e.ParentId, eh.Level + 1" +
                  "   from Equipment e" +
                  "   inner join Hierachy eh" +
                  "      on e.Id = eh.ParentId" +
                  " )" +
                  " select Id, Name, ParentId" +
                  " from Hierachy" +
                  " where Level > 0";
        var list = session.CreateSQLQuery(sql)
            .AddEntity(typeof(Equipment))
            .SetGuid("id", equipmentId)
            .List<Equipment>();
        return list;
    }
}

Note that we had just to adjust the inner join between the Equipment table and the Hierarchy (temp) table. Again the last where statement in the SQL assures that the given equipment is not included in the list of ancestors.

An alternative approach

We can also choose another approach for the tree problem. The solution I want to show works for any database even if it does not support hierarchical queries. This time our simple domain model looks as follows

image

Here we have a node object which can have a parent and a collection of children. Additionally we have defined the two collections descendants and ancestors which contain all descendants (children, children of the children and so on) and all parents of the given node.

The code for the Node class is given by

public class Node
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public Node Parent { get; set; }
    public ISet<Node> Children { get; set; }
 
    public ISet<Node> Ancestors { get; set; }
    public ISet<Node> Descendants { get; set; }
}

The mapping for the node is defined as

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="TreeStructure"
                   namespace="TreeStructure">
  <class name="Node">
    <id name="Id">
      <generator class="guid"/>
    </id>
    <property name="Name" length="50" not-null="true" unique="true"/>
 
    <many-to-one name="Parent" class="Node" column="ParentId" />
 
    <set name="Children" inverse="true" cascade="all" >
      <key column="ParentId" foreign-key="fk_Node_ParentNode"/>
      <one-to-many class="Node"/>
    </set>
 
    <set name="Descendants" table="NodeHierarchy" inverse="true" >
      <key column="ParentId" foreign-key="fk_HierarchyNode_ParentNode"/>
      <many-to-many class="Node" column="ChildId" foreign-key="fk_HierarchyNode_ChildNode" />
    </set>
 
    <set name="Ancestors" table="NodeHierarchy" >
      <key column="ChildId" /> 
      <many-to-many class="Node" column="ParentId" /> 
    </set>
  </class>
</hibernate-mapping>

Note that we define the descendants and ancestors of a node as a many-to-many relation in the database. So the SQL script created by the SchemaExport class of NHibernate is

if exists (select 1 from sys.objects 
           where object_id = OBJECT_ID(N'[fk_Node_ParentNode]') 
           AND parent_object_id = OBJECT_ID('Node'))
  alter table Node  drop constraint fk_Node_ParentNode
 
if exists (select 1 from sys.objects 
           where object_id = OBJECT_ID(N'[fk_HierarchyNode_ChildNode]') 
           AND parent_object_id = OBJECT_ID('NodeHierarchy'))
  alter table NodeHierarchy  drop constraint fk_HierarchyNode_ChildNode
 
if exists (select 1 from sys.objects 
           where object_id = OBJECT_ID(N'[fk_HierarchyNode_ParentNode]') 
           AND parent_object_id = OBJECT_ID('NodeHierarchy'))
  alter table NodeHierarchy  drop constraint fk_HierarchyNode_ParentNode
 
if exists (select * from dbo.sysobjects 
           where id = object_id(N'Node') 
           and OBJECTPROPERTY(id, N'IsUserTable') = 1) 
  drop table Node
 
if exists (select * from dbo.sysobjects 
           where id = object_id(N'NodeHierarchy') 
           and OBJECTPROPERTY(id, N'IsUserTable') = 1) 
  drop table NodeHierarchy
 
create table Node 
(
  Id UNIQUEIDENTIFIER not null, 
  Name NVARCHAR(50) not null unique, 
  ParentId UNIQUEIDENTIFIER null, 
  primary key (Id))
 
create table NodeHierarchy 
(
  ParentId UNIQUEIDENTIFIER not null, 
  ChildId UNIQUEIDENTIFIER not null, 
  primary key (ParentId, ChildId)
)
 
alter table Node add constraint fk_Node_ParentNode 
foreign key (ParentId) references Node
 
alter table NodeHierarchy add constraint fk_HierarchyNode_ChildNode 
foreign key (ChildId) references Node
 
alter table NodeHierarchy add constraint fk_HierarchyNode_ParentNode 
foreign key (ParentId) references Node

we can see here that the script creates a n-to-m mapping table called NodeHierarchy as well as the necessary foreign keys between this table and the table Node.

To account for this special situation I define an AddChild method on the Node class

public virtual void AddChild(Node childNode)
{
    Children.Add(childNode);
    childNode.Parent = this;
    childNode.Ancestors.AddAll(this.Ancestors);
    childNode.Ancestors.Add(this);
    this.Descendants.Add(childNode);
}

This method is responsible for the book-keeping when adding a new child node to an existing node.

If I now want to eager load a node given by its id with all collections populated then I can use code similar to this one

public Node GetAggregateById(Guid nodeId)
{
    using (var session = SessionManager.OpenSession())
    {
        var sql = "from Node e" +
                  " left join fetch e.Parent p" +
                  " left join fetch e.Children c" +
                  " where e.Id = :id";
        var node = session.CreateQuery(sql)
            .SetGuid("id", nodeId)
            .UniqueResult<Node>();
 
        // load the ancestors
        var sql2 = "from Node e" +
                  " left join fetch e.Ancestors a" +
                  " where e.Id = :id";
        node = session.CreateQuery(sql2)
            .SetGuid("id", nodeId)
            .UniqueResult<Node>();
 
        // load the descendants
        var sql3 = "from Node e" +
                  " left join fetch e.Descendants d" +
                  " where e.Id = :id";
        node = session.CreateQuery(sql3)
            .SetGuid("id", nodeId)
            .UniqueResult<Node>();
 
        return node;
    }
}
For an in depth discussion of how to eager load a complex object graph please refer to this post.
Note that depending on the depth of the tree you should eventually avoid to eager load the descendants collection since this collection can become huge... In may sample I assume a tree with limited depth (e.g. less than 5) and a limited amount of children per node (e.g. less than 5).
 
Enjoy
Blog Signature Gabriel .

Published at

Loading a complex object graph

Lately I had the joy to load a complex object graph from a (legacy) MS Access database. Some findings:

  • MS Access does not support the multi-query or multi-criteria API.
  • My first implementation using lazy load was very very slow since it created way to many database hits

The domain model

Let's have a look at the (simplified) domain model. The object graph I am talking about represents a chart with several data series in it. Each data series (or curve) consists of one to many segments. Between two successive segments there is always a segment transition.

image

In this simplified model I only have one curve in my chart. Each segment of the curve has some additional segment data and plot details. All but the last segment of the curve have also a transition (to a next segment). The transition also has plot details. Each segment and transition have a collection of data points. The SegmentPoint and TransitionPoint classes contain some additional data like a sort index, whether or not the data point is active or not, etc.

Now I can load this object graph in a default way and make it populate by NHibernate (which in turn uses lazy loading), or I can tune my NHibernate queries and use eager loading to populate the object graph.

Assume that my curve has 3 segments (and thus 2 transitions between the segments) and a total of 20 data points (distributed to the 3 segments and 2 transitions).

Using Lazy Loading

Let us use lazy loading as below

int chartId = ...;  //some id
var chart = _session.Get<Chart>(chartId);
DumpChart(chart);

Note that the DumpChart() method just transverses the whole object tree an accesses some of the properties of each object. This causes the objects to be (lazy) loaded if necessary.

In doing so I get A LOT of queries hitting the database! In total I have counted the incredible number of 35 select statements. If my curve would have had more segments and more data points the situation would have been even worse!

NHibernate: SELECT chart0_.Id as Id0_0_, chart0_.MainCurveId as MainCurv2_0_0_ FROM Chart chart0_ WHERE chart0_.Id=@p0; @p0 = '1'
NHibernate: SELECT curve0_.Id as Id1_0_, curve0_.Name as Name1_0_ FROM Curve curve0_ WHERE curve0_.Id=@p0; @p0 = '1'
NHibernate: SELECT segments0_.CurveId as CurveId1_, segments0_.Id as Id1_, segments0_.Id as Id2_0_, segments0_.Name as Name2_0_, segments0_.TransitionId as Transiti3_2_0_, segments0_.SegmentDataId as SegmentD4_2_0_, segments0_.PlotDetailsId as PlotDeta5_2_0_ FROM Segment segments0_ WHERE segments0_.CurveId=@p0; @p0 = '1'
NHibernate: SELECT points0_.SegmentId as SegmentId1_, points0_.Id as Id1_, points0_.Id as Id5_0_, points0_.DataPointId as DataPoin2_5_0_ FROM SegmentPoint points0_ WHERE points0_.SegmentId=@p0; @p0 = '1'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '1'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '2'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '3'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '4'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '5'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '6'
NHibernate: SELECT plotdetail0_.Id as Id4_0_, plotdetail0_.LineColor as LineColor4_0_ FROM PlotDetails plotdetail0_ WHERE plotdetail0_.Id=@p0; @p0 = '1'
NHibernate: SELECT segmentdat0_.Id as Id8_0_, segmentdat0_.Data as Data8_0_ FROM SegmentData segmentdat0_ WHERE segmentdat0_.Id=@p0; @p0 = '1'
NHibernate: SELECT transition0_.Id as Id3_0_, transition0_.Name as Name3_0_, transition0_.PlotDetailsId as PlotDeta3_3_0_ FROM Transition transition0_ WHERE transition0_.Id=@p0; @p0 = '1'
NHibernate: SELECT points0_.TransitionId as Transiti3_1_, points0_.Id as Id1_, points0_.Id as Id6_0_, points0_.DataPointId as DataPoin2_6_0_ FROM TransitionPoint points0_ WHERE points0_.TransitionId=@p0; @p0 = '1'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '7'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '8'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '9'
NHibernate: SELECT points0_.SegmentId as SegmentId1_, points0_.Id as Id1_, points0_.Id as Id5_0_, points0_.DataPointId as DataPoin2_5_0_ FROM SegmentPoint points0_ WHERE points0_.SegmentId=@p0; @p0 = '2'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '10'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '11'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '12'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '13'
NHibernate: SELECT plotdetail0_.Id as Id4_0_, plotdetail0_.LineColor as LineColor4_0_ FROM PlotDetails plotdetail0_ WHERE plotdetail0_.Id=@p0; @p0 = '3'
NHibernate: SELECT segmentdat0_.Id as Id8_0_, segmentdat0_.Data as Data8_0_ FROM SegmentData segmentdat0_ WHERE segmentdat0_.Id=@p0; @p0 = '2'
NHibernate: SELECT transition0_.Id as Id3_0_, transition0_.Name as Name3_0_, transition0_.PlotDetailsId as PlotDeta3_3_0_ FROM Transition transition0_ WHERE transition0_.Id=@p0; @p0 = '2'
NHibernate: SELECT points0_.TransitionId as Transiti3_1_, points0_.Id as Id1_, points0_.Id as Id6_0_, points0_.DataPointId as DataPoin2_6_0_ FROM TransitionPoint points0_ WHERE points0_.TransitionId=@p0; @p0 = '2'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '14'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '15'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '16'
NHibernate: SELECT points0_.SegmentId as SegmentId1_, points0_.Id as Id1_, points0_.Id as Id5_0_, points0_.DataPointId as DataPoin2_5_0_ FROM SegmentPoint points0_ WHERE points0_.SegmentId=@p0; @p0 = '3'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '17'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '18'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '19'
NHibernate: SELECT datapoint0_.Id as Id7_0_, datapoint0_.X as X7_0_, datapoint0_.Y as Y7_0_ FROM DataPoint datapoint0_ WHERE datapoint0_.Id=@p0; @p0 = '20'
NHibernate: SELECT plotdetail0_.Id as Id4_0_, plotdetail0_.LineColor as LineColor4_0_ FROM PlotDetails plotdetail0_ WHERE plotdetail0_.Id=@p0; @p0 = '5'

But fortunately I can do better!

Using Eager Loading

By using eager loading I can reduce the number of queries down to 3 (in this simplified sample). That's a factor of 10! How do I do that? Here is the code

var chartId = ...;    // some id of an existing chart
var chart = _session.CreateQuery("from Chart chart" +
                                 " inner join fetch chart.MainCurve mc" +
                                 " left join fetch mc.Segments s" +
                                 " left join fetch s.SegmentData sd" +
                                 " left join fetch s.PlotDetails spd" +
                                 " left join fetch s.Transition t" +
                                 " left join fetch t.PlotDetails tpd" +
                                 " where chart.Id=:id")
    .SetInt32("id", chartId)
    .UniqueResult<Chart>();
 
var chart2 = _session.CreateQuery("from Chart chart" +
                                  " inner join fetch chart.MainCurve mc" +
                                  " left join fetch mc.Segments s" +
                                  " left join fetch s.Points sp" +
                                  " left join fetch sp.DataPoint dp" +
                                  " where chart.Id=:id")
    .SetInt32("id", chartId)
    .UniqueResult<Chart>();
 
var chart3 = _session.CreateQuery("from Chart chart" +
                                  " inner join fetch chart.MainCurve mc" +
                                  " left join fetch mc.Segments s" +
                                  " left join fetch s.Transition t" +
                                  " left join fetch t.Points tp" +
                                  " left join fetch tp.DataPoint dp" +
                                  " where chart.Id=:id")
    .SetInt32("id", chartId)
    .UniqueResult<Chart>();
 
In the first query I load the curve with all its segments and transitions. I also load the additional segment data of each segment and the plot details of each segment and each transition.

In the second query I load all the data points assigned to each segment of the curve.

And in the third query I load all the data points assigned to each transition of the curve.

When I now call the DumpChart() method NO additional query is generated by NHibernate since the object graph is already fully populated by the above 3 queries.

Please note: the variables chart, chart2 and chart3 in the above code represent all the same object. NHibernate recognizes this since the 3 queries are all referencing the same chart object (that is: the chart object with the same id).

Sample Code

As usual you can find the code to this sample here.

Summary

NHibernate provides us an easy way to populate even a very complex object graph by using lazy loading. One just has to navigate through the object graph and when accessing a specific object (or its properties) NHibernate dynamically populates the object from the database if needed. The disadvantage of this is that NHibernate possibly generates a huge number of database requests until the whole object graph is fully populated.

By using the eager loading techniques provided by NHibernate I could dramatically improve the speed to populate a complex object graph.

Enjoy

Blog Signature Gabriel .

Published at

Create and Update Database Schema

Introduction

When developing an application using DDD one starts by trying to define a model of the domain for/in which the application should be used. At the same time you try to establish the so called ubiquitous language. At some point you might need to store and or retrieve data into or from a data source. Very often this data source is a relational database. But it's not necessarily always the case. It could as well be a web service or a XML document. That leads me to the notion that "the database is just an implementation detail of the application". Or if I turn this sentence a little bit around "...it should not be the database (-schema) that determines the design of an application but rather should the database schema be a natural outcome of the domain model...". I know, this is NOT what a DBA likes to hear. But trust me I have developed many applications in the past where the first thing that was designed of the application was the entity relationship diagram (ERD)... I have also implemented quite a lot of stored procedures on Oracle and SQL server in the past. So I know both sides of the argument.

Assuming that the database schema should be an implementation detail of the overall application it would be great if the schema could be somehow auto-generated from the domain model. As you might expect, when using NHibernate as the ORM tool this is possible. We have to distinguish between the two possibilities

  • (re-) create a new schema from scratch
  • updating an existing schema

Create Schema

The model

To start we define a very basic model

image

The Mappings

In our data layer we define the two mapping files Product.hbm.xml and Category.hbm.xml. The former's content is

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   namespace="Domain"
                   assembly="Domain">
  <class name="Product">
    <id name="Id">
      <generator class="guid"/>
    </id>
    <property name="Name"/>
    <many-to-one name="Category" class="Category"/>
  </class>
</hibernate-mapping>

and the latter's content is

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   namespace="Domain"
                   assembly="Domain">
  <class name="Category">
    <id name="Id">
      <generator class="guid"/>
    </id>
    <property name="Name"/>
  </class>
</hibernate-mapping>

Note that we have defined only the absolute minimum needed and rely heavily on the (meaningful) defaults provided by NHibernate.

Tests

To analyze the database schema creation script generated by NHibernate we write the following test

[TestFixture]
public class CreateSchema_Fixture
{
    private Configuration _cfg;
 
    [SetUp]
    public void SetupContext()
    {
        _cfg = new Configuration();
        _cfg.Configure();
        _cfg.AddAssembly(Assembly.LoadFrom("DataLayer.dll"));
    }
 
    [Test]
    public void Create_a_database_schema_creation_script()
    {
        var export = new SchemaExport(_cfg);
        var sb = new StringBuilder();
        TextWriter output = new StringWriter(sb);
        export.Execute(true, false, false, false, null, output);
    }
}

Note that the configuration file hibernate.cfg.xml has the following content in our case

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
    <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    <property name="connection.connection_string">Server=(local);Database=NHibernateFAQ;Integrated Security=SSPI;</property>
    
    <property name="show_sql">true</property>
  </session-factory>
</hibernate-configuration>

That is, we are using a SQL Server 2005 database called NHibernateFAQ. It is not necessary to have SQL Server 2005 installed though since we are only generating (and analyzing) the scripts generated by NHibernate and not accessing the database itself!

The output generated by the above test is similar to this

if exists (select 1 from sys.objects 
           where object_id = OBJECT_ID(N'[FK1F94D86A9F364CC5]') 
           AND parent_object_id = OBJECT_ID('Product'))
    alter table Product  drop constraint FK1F94D86A9F364CC5
 
if exists (select * from dbo.sysobjects 
           where id = object_id(N'Product') 
           and OBJECTPROPERTY(id, N'IsUserTable') = 1) 
    drop table Product
if exists (select * from dbo.sysobjects 
           where id = object_id(N'Category') 
           and OBJECTPROPERTY(id, N'IsUserTable') = 1) 
    drop table Category
 
create table Product (Id UNIQUEIDENTIFIER not null, 
                      Name NVARCHAR(255) null, 
                      Category UNIQUEIDENTIFIER null, 
                      primary key (Id))
create table Category (Id UNIQUEIDENTIFIER not null, 
                       Name NVARCHAR(255) null, 
                       primary key (Id))
 
alter table Product add constraint FK1F94D86A9F364CC5 
foreign key (Category) references Category

That's really wonderful for a quick shot!

The default for a column is that it is nullable and the default type and length for a string type field is NVARCHAR(255).

Mandatory columns and maximal length of column

But there are a few details that we might want to improve. First we want to make the Name columns mandatory (NOT NULL). Nothing easier than that; just add an attribute not-null="true" to the mapping files where appropriate. Also we want to limit the length of the Name column to given amount, e.g. 50 characters. Just add a length="50" to the appropriate property of the mapping files. The create table part of the schema creation script is then

create table Product (Id UNIQUEIDENTIFIER not null, 
                      Name NVARCHAR(50) not null, 
                      Category UNIQUEIDENTIFIER null, 
                      primary key (Id))
 
create table Category (Id UNIQUEIDENTIFIER not null, 
                       Name NVARCHAR(20) not null, 
                       primary key (Id))

Foreign Keys

There is still a detail in the script that might disturb you. It's the name of the foreign key constraint between the Product and the Category tables. If we want to choose a name we can use the foreign-key attribute on the many-to-one node of the mapping file, e.g.

<many-to-one name="Category" class="Category" foreign-key="fk_Product_Category"/>

now the corresponding snippet of the script is

if exists (select 1 from sys.objects 
           where object_id = OBJECT_ID(N'[fk_Product_Category]') 
           AND parent_object_id = OBJECT_ID('Product'))
    alter table Product  drop constraint fk_Product_Category
...
alter table Product add constraint fk_Product_Category 
foreign key (Category) references Category

Unique Constraints

If we want to guarantee that the Name property of the Category class is unique we can do this by either using business logic to enforce this requirement or define a unique constraint on the database. Let's have a look at the latter. Just add the attribute unique="true" to the mapping of the Name property in the mapping file for the Category class. That is

<property name="Name" not-null="true" length="20" unique="true"/>

and the script generated is this

create table Category (
    Id UNIQUEIDENTIFIER not null, 
    Name NVARCHAR(20) not null unique, 
    primary key (Id)
)

If you want to define a unique constraint which spans multiple columns then you have to resort to the attribute unique-key. Let's assume we have a Person class like

public class Person
{
    public Guid Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

and we want to define a unique constraint on the combination of the FirstName and LastName columns then our mapping file looks like this

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   namespace="Domain"
                   assembly="Domain">
  <class name="Person">
    <id name="Id">
      <generator class="guid"/>
    </id>
    <property name="FirstName" not-null="true" length="50" unique-key="uk_Person_Name"/>
    <property name="LastName" not-null="true" length="50" unique-key="uk_Person_Name"/>
  </class>
</hibernate-mapping>
Note that the name you choose for the unique-key is not important (here "uk_Person_Name"). Just use the same name for all columns that make up for a unique constraint. The create table script generated by NHibernate is then
create table Person (
    Id UNIQUEIDENTIFIER not null, 
    FirstName NVARCHAR(50) not null, 
    LastName NVARCHAR(50) not null, 
    primary key (Id),
    unique (FirstName, LastName)
)

Indices

We might also want to tune our database schema and define some indices. Often we might search for a product by its name and thus the Name column might be a good candidate for an index. How can we do this. Well it's again very easy. Just add the attribute index to the right property tag in the product mapping file and provide a name for the index. That is

<property name="Name" not-null="true" length="50" index="idx_Product_Name"/>

now our create script will look like this (note the second last statement where the index is created)

create table Category (Id UNIQUEIDENTIFIER not null, ...)
create table Product (Id UNIQUEIDENTIFIER not null, ...)
create index idx_Product_Name on Product (Name)
alter table Product add constraint fk_Product_Category ...

Check Constraints

We can also define some check constraints on our columns in the database. Let's assume our product has a UnitsOnStock property which must be greater or equal than zero. To define this constraint on the database column we can define the mapping of UnitsOnStock as follows

<property name="UnitsOnStock" not-null="true" >
  <column name="UnitsOnStock" check="UnitsOnStock >= 0"/>
</property>

Note that there is no check attribute defined for the property tag. Thus we have to use the child tag column for this purpose. The create table script is then

create table Product (
    Id UNIQUEIDENTIFIER not null, 
    Name NVARCHAR(50) not null, 
    UnitsOnStock INT null check( UnitsOnStock >= 0) , 
    Category UNIQUEIDENTIFIER not null, 
    primary key (Id)
)

Update Schema

Once we have an existing database schema which we cannot re-create from scratch (because we might already have a first version of our application in production with productive data...) we need another technique. Fortunately NHibernate provides us the possibility to update an existing schema, that is NHibernate creates an update script which can the be applied to the database.

As usual we want to define a unit test for this situation. In the setup for the unit test I'll predefine a first version of my database schema. This time we need to have a database installed on the system (in our case SQL Server 2005) since this first version of the schema is generated in the database otherwise update schema will not work.

So let's have a look at the setup

[TestFixture]
public class UpdateSchema_Fixture
{
    private Configuration _cfg;
 
    public const string product_xml =
        "<?xml version='1.0' encoding='utf-8' ?>"+
        "<hibernate-mapping xmlns='urn:nhibernate-mapping-2.2'"+
        "                   namespace='Domain'"+
        "                   assembly='Domain'>"+
        "  <class name='Product'>"+
        "    <id name='Id'>"+
        "      <generator class='guid'/>"+
        "    </id>"+
        "    <property name='Name' not-null='true' length='20'/>" +
        "  </class>"+
        "</hibernate-mapping>";
    public const string category_xml = 
        "<?xml version='1.0' encoding='utf-8' ?>"+
        "<hibernate-mapping xmlns='urn:nhibernate-mapping-2.2'"+
        "                   namespace='Domain'"+
        "                   assembly='Domain'>"+
        "  <class name='Category'>"+
        "    <id name='Id'>"+
        "      <generator class='guid'/>"+
        "    </id>"+
        "  </class>"+
        "</hibernate-mapping>";
 
    [SetUp]
    public void SetupContext()
    {
        // Setup "old" database schema
        _cfg = new Configuration();
        _cfg.Configure();
        _cfg.AddXml(product_xml);
        _cfg.AddXml(category_xml);
        var export = new SchemaExport(_cfg);
        export.Execute(false, true, false, false);
    }
}

I define 2 strings containing the (first version of the) mapping files for the Category and the Product class. In the SetupContext method I create a configuration object and feed it with these two mapping XML fragments. I then export this schema to the database by creating an instance of the SchemaExport class and calling the Execute method.

Note that the Category mapping fragment does not contain a mapping for the Name column and the Product mapping fragment does not contain a mapping for the relation to the Category class as well as no definition of the UnitsInStock column.

Now I want to test the UpdateSchema class and thus implement the following test

[Test]
public void Update_an_existing_database_schema()
{
    _cfg = new Configuration();
    _cfg.Configure();
    _cfg.AddAssembly(Assembly.LoadFrom("DataLayer.dll"));
    var update = new SchemaUpdate(_cfg);
    update.Execute(true, false);
}

The update script generated by NHibernate is

alter table Category add Name NVARCHAR(20) unique
alter table Product add UnitsOnStock INT check(UnitsOnStock >= 0) 
alter table Product add Category UNIQUEIDENTIFIER
alter table Product add constraint 
fk_Product_Category foreign key (Category) references Category

As expected I only get alter statements for existing tables and create statements for the elements missing so far.

Code

You can find the code here. Download it with a SVN client like TortoiseSVN. It's a VS 2008 project.

Summary

When developing a application using DDD the database is often considered an "implementation detail". NHibernate provides us tools to auto-generate create and alter scripts for the database schema from the domain model. I have shown you, by using a simple domain model how to create a schema from scratch and how to alter a pre-existing database schema. I have also discussed various optimization techniques used when creating database schemas as there are unique constraints, indices and check constraints.

Enjoy

Blog Signature Gabriel .

Published at

NHibernate and Castle Active Record (Part 1)

Introduction

The Castle ActiveRecord project is an implementation of the ActiveRecord pattern for .NET. The ActiveRecord pattern consists on instance properties representing a record in the database, instance methods acting on that specific record and static methods acting on all records.

Castle ActiveRecord is built on top of NHibernate, but its attribute-based mapping free the developer of writing XML for database-to-object mapping, which is needed when using NHibernate directly.

You can find the home page of the Castle project here.

How will we use it?

My intent is not to implement the ActiveRecord pattern but rather use ActiveRecord

  1. as an alternative way to define the mapping between my domain objects and the relational database.
  2. to simplify the initialization of NHibernate (I'm not so sure about this...)

In my previous posts (here and here) I have shown you how to define the mapping between domain objects and database tables by writing XML documents. Active Record allows me to decorate my domain objects with attributes which define the mapping instead of (hand-) coding XML documents.

Downloading and compiling the Castle Active Record Trunk

If you have never downloaded and compiled OSS software from a SVN repository before please refer to my previous post about preparing your system for NHibernate which you can find here.

I assume you have TortoiseSVN installed as your SVN client.

Make a new sub-folder called 'Castle' in your OSS folder (e.g. m:\dev\OSS\Castle). Right click on the folder an select 'SVN Checkout...'. Enter the URL 'http://svn.castleproject.org:8080/svn/castle/trunk/' in the Checkout dialog and press OK. The Castle stack will be downloaded. Depending on the bandwidth of your Internet connection this may take a while. The whole Castle stack contains more software than we need at the moment but let's just download all and ignore the parts we don't need. The whole download is around 21 MB.

image

When the download is finished you can compile the Castle stack. This is an automated process.

Unit Tests during the build process

During the build a lot of unit tests will be executed. For this we either need NUnit or MbUnit on our system. If you don't  have it you can e.g. download NUnit from here. Download just the zip file containing the binaries for .NET 2.0 (at the time of this writing it's the file 'NUnit-2.4.7-net-2.0.zip'). Extract the binaries into a sub-folder of your OSS directory (e.g. m:\dev\OSS\nunit).

Building the Castle Stack

Open a command console and navigate to the directory where you have downloaded Castle (e.g. m\dev\OSS\Castle). Assuming that NAnt is also installed in the OSS directory enter the following command

..\NAnt\bin\nant.exe -D:nunit-console=<path to nunit-console.exe>

where at the place of <path to nunit-console.exe> you enter the path where you have unzipped/installed NUnit. In our case this is 'm:\dev\OSS\NUnit\bin\NUnit-Console.exe'.

Now the whole Castle stack is compiled and all tests are executed. This can take a while. On my machine it took about 2.5 minutes. The overall build may fail but still the assemblies are created (the reason of the overall failure might be that some of the Unit test fail. Remember that we are on the Trunk and this is under constant development. Sometimes some of the tests may thus fail.). The result on my machine was as follows

image

After building the Castle stack you should find a new sub-folder 'build' in the Castle folder.

Using Active Record

External dependencies of the Solution

For an introduction on how to setup a new solution please refer to this post. You can now copy all the necessary external assemblies on which the solution depends into the SharedLibs folder in your solution tree. You should copy all files (including NHibernate) from the build folder of Castle which was created during the build process described above.  For this solution you need at least the following files

image

The sql*.dll are in the folder since we are using SQL Server Compact edition as a database. If you have read the previous posts about using NHibernate (e.g. here and here) the only new files are Castle.ActiveRecord.dll and Castle.Components.Validator.dll.

The Domain Model and the Mapping

To have a good comparison let's take the same domain model as in this post. Below is the class diagram of the domain.

image

Now instead of writing a domain class and then a XML mapping document we now only write the domain class and decorate it and its members with attributes. During initialization ActiveRecord will automatically generate the XML mapping documents for us which NHibernate requires for the object-relational mapping.

When using attributes the Order class will look like this

using System;
using Castle.ActiveRecord;
using Iesi.Collections.Generic;
using NHibernateAndActiveRecord.Domain;
 
namespace NHibernateAndActiveRecord.Domain
{
    [ActiveRecord(Table = "Orders")]
    public class Order
    {
        public Order()
        {
            OrderLines = new HashedSet<OrderLine>();
        }
 
        [PrimaryKey(Generator = PrimaryKeyType.Guid)]
        public virtual Guid Id { get; set; }
 
        [BelongsTo(NotNull = true)]
        public virtual Customer Customer { get; set; }
 
        [Property]
        public virtual string OrderNumber { get; set; }
 
        [Property]
        public virtual DateTime OrderDate { get; set; }
 
        [HasMany(Table = "OrderLine", 
                 ColumnKey = "OrderId", 
                 Cascade = ManyRelationCascadeEnum.AllDeleteOrphan)]
        public virtual ISet<OrderLine> OrderLines { get; set; }
    }
}

compared to a typical XML mapping document this is much more wrist friendly, isn't it. Some people also argue that attributes help to document the code, since I can immediately see e.g. which is the primary key and which property values should never be null, etc. I do not have to consult another file but can just look at the domain class to have the "full" picture. On the other hand the attributes also "clutter" my nice code and I partially violate the SoC pattern since mapping is not part of the domain in a DDD world.

Now let's look at the OrderLine class

using System;
using Castle.ActiveRecord;
 
namespace NHibernateAndActiveRecord.Domain
{
    [ActiveRecord]
    public class OrderLine
    {
        [PrimaryKey(Generator = PrimaryKeyType.Guid)]
        public virtual Guid Id { get; set; }
 
        [Property(NotNull = true)]
        public virtual int Amount { get; set; }
 
        [Property(NotNull = true, Length = 50)]
        public virtual string ProductName { get; set; }
    }
}

Here I have defined that Amount and ProductName cannot be null (this will be used for the generation of the database schema - there will be not null constraints on the corresponding table column). I also have defined that the maximal length of the ProductName cannot exceed 50 characters (also used for schema generation).

Finally the Customer class

using System;
using Castle.ActiveRecord;
 
namespace NHibernateAndActiveRecord.Domain
{
    [ActiveRecord]
    public class Customer
    {
        [PrimaryKey(Generator = PrimaryKeyType.Guid)]
        public virtual Guid Id { get; set; }
 
        [Property(NotNull = true, Length = 50)]
        public virtual string CompanyName { get; set; }
    }
}

That's it. Our domain and mapping is complete. We can now write our tests similar to the once we used in this post.

Unit Tests

Add an xml document to your test project and call it ActiveRecord.cfg.xml (similar to what you do when you ONLY use NHibernate). Add the following content to the file

<?xml version="1.0" encoding="utf-8" ?>
 
<activerecord>
 
  <config>
    <add key="connection.provider"
         value="NHibernate.Connection.DriverConnectionProvider" />
    <add key="dialect"
         value="NHibernate.Dialect.MsSqlCeDialect" />
    <add key="connection.driver_class"
         value="NHibernate.Driver.SqlServerCeDriver" />
    <add key="connection.connection_string"
         value="Data Source=SampleDb.sdf" />
    
    <add key="show_sql"
         value="true" />
  </config>
 
</activerecord>

Set the Copy to Output Directory to Copy always.

Note: we are using SQL server compact edition in this case (the second, third and fourth entry in the XML are specific for this database).

Add an new item of type LocalDatabase to the test project and call it SampleDb.sdf.

Still in the test project add a reference to the System.Data.SqlServerCe.dll in the SharedLibs folder. This assembly contains the ado.net driver for SQL server compact edition.

Open the properties page of the test project and add the following command in the "Pre-build event command line" text box

copy $(ProjectDir)..\..\SharedLibs\sqlce*.dll $(ProjectDir)$(OutDir)

This command copies all the SQL server CE files from the SharedLibs folder to the target folder of the test project. Note: this is important, otherwise the test will not run. Also note that this is only needed if you use SQL server CE.

The first unit test we write will test whether we can successfully create the database schema or not. This is always a good test if your new to ActiveRecord. Add a new class CreateSchema_Fixture.cs to the test project and add the code below

using Castle.ActiveRecord;
using Castle.ActiveRecord.Framework.Config;
using NHibernateAndActiveRecord.Domain;
using NUnit.Framework;
 
namespace NibernateAndActiveRecord.Tests
{
    [TestFixture]
    public class CreateSchema_Fixture
    {
        [Test]
        public void Can_initialize_and_create_schema()
        {
            var configurationSource = new XmlConfigurationSource("ActiveRecord.cfg.xml");
            ActiveRecordStarter.Initialize(typeof(Customer).Assembly, configurationSource);
            ActiveRecordStarter.CreateSchema();
        }
    }
}

In the first line of the test we provide ActiveRecord with the necessary configuration info. In the second line we tell ActiveRecord to initialize itself (and NHibernate) with the given configuration info as well as the assembly in which the domain classes are implemented (and which also contains the mapping info since we use attributes). Then in the third line we create the schema. If there is already a schema in the db this will be deleted first.

If you have done every thing right, then the test should succeed.

Now we can continue to test our domain model. Let's first implement a base fixture class to free us from repeating code again and again. I suggest a class as follows

using Castle.ActiveRecord;
using Castle.ActiveRecord.Framework.Config;
using NHibernateAndActiveRecord.Domain;
using NUnit.Framework;
 
namespace NibernateAndActiveRecord.Tests
{
    [TestFixture]
    public class TestFixtureBase
    {
        [TestFixtureSetUp]
        public void TestFixtureSetUp()
        {
            var configurationSource = new XmlConfigurationSource("ActiveRecord.cfg.xml");
            ActiveRecordStarter.Initialize(typeof(Customer).Assembly, configurationSource);
        }
 
        [SetUp]
        public void SetupContext()
        {
            ActiveRecordStarter.CreateSchema();
            Before_each_test();
        }
 
        [TearDown]
        public void TearDownContext()
        {
            After_each_test();
        }
 
        protected virtual void Before_each_test()
        { }
 
        protected virtual void After_each_test()
        { }
    }
}

This class is equivalent to the class presented in this post on NHibernate. Once for each test session I configure ActiveRecord (and implicitly NHibernate). Before each single test I recreate the database schema to avoid any side effects leaking from one test to another. I also provide virtual methods which can be overridden in the child classes to execute specific code before or after each test.

Summary

I have introduced Castle ActiveRecord as an alternative way to use NHibernate. It's a layer on top of NHibernate and simplifies in many cases the usage of NHibernate. I have shown you how you can get the latest code from the source repository and compile it. I have then setup a simple domain model and defined a test fixture base class.

I'll continue to implement the tests in part 2 of this series. So keep ready...

Enjoy

Blog Signature Gabriel.

Published at

Next Page