Wednesday, September 27, 2006

I'm not dead

I’m just posting this to let my readers know that I am not dead

I’ve been eager to finish the articles on Domain Driven Design and NHibernate, however work has been very busy lately, combined with kids soccer, volleyball, cub scounts, and other activities….there’s not enough time in a day!

Ahh, and I’d also like to personally thank Aaron Murrell and Ayende Rahien for their hugely appreciated assistance in overcoming some very obscure issues.  Thanks guys!

Tuesday, September 05, 2006

Reason #462 Why I don't like VB.NET

Reason #462 Why I don't like VB.NET:

VB.NET attributes cannot have variable arguments.  What do I mean?

The following code does NOT work in VB.NET:

Public Class MyCustomAttribute

    Inherits Attribute

 

    Public Sub New(ByVal ParamArray vals() As String)

    End Sub

 

End Class

It compiles, but when you try to use this attribute on a member you’ll get an error:  “Attribute constructor argument is a 1-dimension array of string which is not Integral, float, etc…..”

In C# this works perfectly fine.  Why is this?

To provide a workaround for this issue I just accept a single pipe-delimited string and .Split it on the pipe to get my array.  A tad on the ugly side, but it works.

Now playing: Third Eye Open - Intolerance

Friday, September 01, 2006

A Journey with Domain Driven Design (and NHibernate) - Part 6

Welcome back!  In Part 5 we finished off with a table structure and the beginnings of NHibernate.  We’ll dive in deeper with NHibernate and mapping in this article.

(part 1 was Dugg, which was quite exciting to me!  It has also increased the traffic around here a little bit!  If you’re enjoying the series, why not Digg it some more?)

Currently we can initialize our SessionFactory which reads the configuration file and loads our domain model assembly.  This step is where NHibernate will parse our mapping files (once we add them).

So let’s take a step back and ask the question that’s probably on your minds already: how do we get our classes mapped to the database using NHibernate?  We have to provide a mapping file.  An NHibernate mapping file is an xml file that specifies how your object fields and properties map to database columns.  There are a few ways you can load mapping files into NHibernate, but the easiest I have found is to add them as part of your domain model class library as embedded resources (details below).   I emphasize embedded resources because if you just add the XML files without specifying they will not be recognized automatically by our SessionFactory initialization.

A number of people have asked me to display more source code, and in this article you’ll see the domain model in more detail.  At the end of this article I will post the code that we’ve created so far.

If you are a little scared about writing these mapping files and would rather use a tool to generate it for you that is certainly possible.  Ayende Rahien’s NHibernate Query Analyzer can help with this.  I have found, however, that in order to fully understand how to effectively map your objects, you should write the mapping by hand.  Don’t fret, there is hope with the manual method.  The hope?  Intellisense.  To get nhibernate mapping intellisense in Visual Studio 2005 you can copy the schema file (nhibernate-mapping-2.0.xsd) to C:\Program Files\Microsoft Visual Studio 8\Xml\Schemas.

Now that we have intellisense for our mapping files, we can start creating our mappings.  I choose to have a single mapping file per class, so that they don’t get too cluttered.  There is nothing to stop you from defining your entire object model in a single mapping file, but I avoid this approach.

CropperCapture[26]Starting off with the Person class, we create add a new XML file to our domain model project called Person.hbm.xml.  NHibernate will search our assembly for embedded resources named *.hbm.xml.  If this is mispelled or the file is not marked as an embedded resource the mapping will not be found and NHibernate won’t recognize the object.

 CropperCapture[28]
In these screen shots you can see that I have added the mapping file next to my objects and I right-clicked and selected properties.  Then under the properties pane I clicked on Build Action and changed the value from Compile to Embedded Resource.CropperCapture[27]


 

Let’s take a side-by-side look at our Person class with our People database table.  This will be  a simple mapping because the class contains no complex associations with other classes.

Side-by-side compare3

Here you can see that we simple relate each property in our class to a column in the table.  Address, in this example, is called a component.  What this means is that Address has no table of its own;  all of the address properties are mapped to the containing object’s table.  We say that Address is a component of Person.  I chose to represent it this way in the object model to delineate the model and separate concerns.  It is a common occurrence for the database, however, to not employ unnecessary joins for simple associations such as this one (for performance reasons).

We start by opening our (now blank) Person.hbm.xml file.  In order to tell Visual Studio that we want intellisense for this file, we have to create the document element (the root) called <hibernate-mapping>.  We tell it which schema to use, and then intellisense kicks in.  Also in this root element the assembly and namespace are defined.  This saves us from typing it every time in the mapping file.  For example, within this mapping file, Person will refer to the strongly typed Flux88.Videocracy.DomainModel.Person, Flux88.DomainModel.Person (see?  less typing!).

*note:  I have changed the Phone number properties to be plain-jane strings instead of the Phone Number class that you may have seen earlier.  While this is a good addition, it complicates the mapping a tad too much right at first, so I removed it in favor of a simple mapping for now.

<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0"

                  assembly="Flux88.Videocracy.DomainModel"

                  namespace="Flux88.Videocracy.DomainModel">

 

</hibernate-mapping>

The next element in this mapping will be our class:

<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0"

                  namespace="Flux88.Videocracy.DomainModel"

                  assembly="Flux88.Videocracy.DomainModel">

 

  <class name="Person" table="People">

 

    <id name="Id" access="nosetter.camelcase-underscore"

          column="PersonId" type="Int32">

      <generator class="identity" />

    </id>

 

  </class>

 

</hibernate-mapping>

I have emboldened the new text.  The name property here tells NHibernate that we are mapping our Person class, from the assembly/namespace defined above.  The table attribute tells NHibernate which table this class maps to.  There are a few other advanced attributes that we may define, but these will suffice for this mapping. 

The first child of our <class> element is the <id> element.  This tells NHibernate what our primary key is.  You can specify a single field or multiple fields (composite-id) and define their type as well.  Here you see that the name attribute refers to our Id property of the Person class.  We do not want consumers of our objects to be able to set arbitrary values in the primary key, so this is a read only property.  As such it does not have a setter, but NHibernate needs to know how it will set the value (otherwise how could it get there?).  We give NHibernate a hint by specifying a predefined access strategy in the access attribute.  nosetter.camelcase-underscore is the access strategy that we will employ.  (This means that since our property is named Id, the private field must be named _id).  There are other access strategies so if you prefer naming such as m_id you can deal with that as well.  We specify the type of our Id property (specifically Ant, which is an NHibernate Type that matches our int).

The last thing you’ll notice is that <id> has a <generator> child element.  This tells NHibernate that we are using MS SQL Identity as our primary key generator.  NHibernate also understands Oracle sequence, hilo, guids and other primary key generators.  (I was happy to learn there is also a neat generator class for guid.comb, which is a sort of “ordered” guid conceived by Jimmy Nilsson – if you are using Guids as primary keys, you should consider this.)

One of the reasons for specifying a generated primary key like this is so that NHibernate easily knows whether or not your object is a brand new object that needs to be inserted or a previously fetched object that might by updated or deleted.  Using a guid, identity, hilo, or sequence we get the benefit of just calling Session.SaveOrUpdate(myObject) and NHibernate knows whether to generate an insert or update behind-the-scenes.

Here’s the rest of the Person class mapping file:

<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0"

                  namespace="Flux88.Videocracy.DomainModel"

                  assembly="Flux88.Videocracy.DomainModel">

 

  <class name="Person" table="People">

 

    <id name="Id" access="nosetter.camelcase-underscore"

          column="PersonId" type="Int32">

      <generator class="identity" />

    </id>

 

    <property name="FirstName" type="String" length="100" column="firstName"

      not-null="true" />

    <property name="LastName" type="String" length="100" column="lastName"

      not-null="true" />

    <property name="HomePhone" type="String" length="50" column="primaryPhone"

      not-null="true" />

    <property name="AltPhone" type="String" length="50" column="altPhone" />

    <property name="DateOfBirth" type="DateTime" column="dateOfBirth"

      not-null="true" />

 

    <component name="Address" class="Address">

      <property name="Line1" type="String" length="100" column="addressLine1"

          not-null="true" />

      <property name="Line2" type="String" length="100" column="addressLine2" />

      <property name="City" type="String" length="100" column="city" />

      <property name="State" type="String" length="50" column="state" />

      <property name="Zip" type="String" length="50" column="zip" />

    </component>

 

  </class>

 

</hibernate-mapping>

Here you can see that the properties are defined, along with their type (and length for strings) as well as their database column name.  The Address component is nested within this mapping and defined with the <component> element.

With me so far?

So basically that’s it.  We have a Person object and it is completely persistable.  You tell NHibernate how to persist your object and you get all of the CRUD operations for free.  You can create a new Person, fill out some properties, and then call Session.SaveOrUpdate(person) to save the person.  Or you can call Session.Load(typeof(Person), personId) to fetch an existing person from the database.  You can also query for Person objects, but we’ll get into that later.  The point is, with NHibernate we are avoiding writing the mundane task of repetitive SQL commands and stored procedures.

Let’s prove that this works with tests.

 The simplest way of seeing if our mapping is working or not is to actually hit the database.  The simplest way to do this is to do a List operation, (basically SELECT * FROM table).  If NHibernate doesn’t recognize your type the test will fail.  If your mapping doesn’t map to valid columns or class properties, the test will fail.  It’s slightly larger in scope than the Unit Tests, but this is actually an integration test, so it’s okay to test a broader scope.

[TestFixture]

public class PersonTester

{

    private int GetPersonCount()

    {

        return Convert.ToInt32(

            DatabaseHelper.ExecuteQuery("SELECT COUNT(*) FROM People"));

    }

 

    [Test]

    public void TestCanListPeople()

    {

        using (NHibernate.ISession session = SessionSource.Current.GetSession())

        {

            IList people = session.CreateCriteria(typeof(Person)).List();

 

 

            Assert.IsNotNull(people, "Person list should not be null.");

            Assert.AreEqual(GetPersonCount(), people.Count,

                "Person list didn't have the right number of elements");

        }

    }

}

This tests gets a list of all of the Person records in the database (currently zero, but that won’t matter).  It compares the count of this list to a SELECT COUNT(*) FROM People, using a helper class.  One thing to note is that I am making this test scale with the database.  It should always return the correct number of people.

I run the test and….

CropperCapture[33]

What?  Our new test passed, but why did CanInitializeSessionSource fail?  Upon a quick inspection, I realize that I have broken a core rule of unit testing:  Each test should run independently of other tests.  The order of test execution should not affect the outcome of the test.  This code:

[Test]

public void CanInitializeSessionSource()

{

    Assert.IsFalse(SessionSource.Current.IsInitialized);

    SessionSource.Current.Initialize();

 

    Assert.IsTrue(SessionSource.Current.IsInitialized);

}

…is assuming that the current Session Source is not initialized.  If another test that uses the SessionSource executes before us (like what happened above) then this Assertion fails.  What we have to do is set our pre-condition explicitly:

[Test]

public void CanInitializeSessionSource()

{

    //make sure we start in a known state

    SessionSource.Current.Close();

 

    Assert.IsFalse(SessionSource.Current.IsInitialized);

    SessionSource.Current.Initialize();

 

    Assert.IsTrue(SessionSource.Current.IsInitialized);

}

This test fails because the .Close() method doesn’t exist yet.  Here is the implementation that passes the test:

 

//SessionSource.cs

 

/// <summary>

/// Closes the current session factory.  The next call

/// to initialize or GetSession will re-initialize the SessionSource

/// </summary>

public void Close()

{

    if (_factory == null)

        return;

     

    _factory.Close();

    _initialized = false;

}

 

And we’re back to all green again.

 

Next we can test to see if we can save a Person object.  To test this we actually have to save it and verify that each property is equal to what it was saved as.  I find this is easier to do by breaking a small rule:  if we write the load functionality and reuse it to help Assert that our Save works, we can cut a few corners.  I welcome any suggestions of a more elegant way of achieving this without resorting to a database query + column/property comparison which is tedious and boring.

 

Starting with the Load, we insert a person record into the database and verify that we can load it properly.  I have written a simple helper class that will assist us with these database operations.  A really quick and dirty convert-dictionary-to-insert statement is a tad on the ugly side, but this isn’t production code and it serves our purpose nicely.  So we insert a test Person record into the database, then we load it and verify that it returns ok.

 

Before I show you this test, keep in mind that since we are inserting data into a (probably) development database, we don’t want this junk data to stick around.  We will be running these tests over and over again, and each time it should clean up nicely.  We can accomplish this easily by using transactions (more on this later).

 

[Test]

public void TestCanLoadAPerson()

{

    TransactionScope tx = new TransactionScope();

 

    try

    {

        //first we need to insert a person               

        Dictionary<string, object> dictionary = new Dictionary<string, object>();

        dictionary.Add("firstName", "Fred");

        dictionary.Add("lastName", "Flinstone");

        dictionary.Add("dateOfBirth", new DateTime(1925, 10, 5));

        dictionary.Add("primaryPhone", "111-222-3333");

        dictionary.Add("altPhone", "444-555-6666");

        dictionary.Add("addressLine1", "123 Rocky Lane");

        dictionary.Add("addressLine2", "#555");

        dictionary.Add("city", "Bedrock");

        dictionary.Add("state", "ZZ");

        dictionary.Add("zip", "12345");

 

        int personId = _datasource.ExecuteDictionaryToInsertCommand(dictionary, "People");

 

        //try and fetch that person

        using (ISession session = SessionSource.Current.GetSession())

        {

 

            Person fred = (Person)session.Load(typeof(Person), personId);

 

            //assert that fred is who we think he is

            Assert.IsNotNull(fred, "Person should not be null");

            Assert.AreEqual(personId, fred.Id, "Id was different");

            Assert.AreEqual("Fred", fred.FirstName, "First Name was different");

            Assert.AreEqual("Flinstone", fred.LastName, "Last Name was different");

            Assert.AreEqual(dictionary["dateOfBirth"], fred.DateOfBirth, "Date of Birth was different");

            Assert.AreEqual("111-222-3333", fred.HomePhone);

            Assert.AreEqual("444-555-6666", fred.AltPhone);

            Assert.AreEqual("123 Rocky Lane", fred.Address.Line1);

            Assert.AreEqual("#555", fred.Address.Line2);

 

        }

    }

    finally

    {

        //cleanup               

        datasource.Dispose();

        tx.Dispose();

    }

}

 

Wow, that’s a long test.  But it’s explicit and easy to follow.  One thing I’d like to point out here is that we are combining standard ADO.NET (the _datasource call above) with NHibernate’s ISession.  It’s difficult to get these 2 to share a single transaction, so I’m using .NET 2.0’s TransactionScope which makes it easy to have a shared transactiont that works on any level.  The downside to this is that it’s 1) slow and 2) requires configuration and enabled services, which sometimes makes it a no-go, depending on your environment.  In other tests I’ll be able to just use NHibernate transactions and everything will be easier.  (YMMV).

 

In writing this test I exposed 2 or 3 different bugs with my mapping (which were then fixed).  This is a benefit of writing the tests along with the code.  If you wait until you have a UI to test all of this manually, you will have waited too long and will have to re-visit all of this code and remember exactly what it does and how to fix little issues.  Our feedback loop is very tight here, and that helps us stay on track and be efficient.  Ok, so this test is passing…. what next?

 

Before this article gets too long (too late?) I want to show one last thing.  We’ll write a CanSavePerson test.  Since we have our load already working, we’ll bend a rule and build on that:

 

[Test]

public void CanSavePerson()

{

    using (ISession session = SessionSource.Current.GetSession())

    {

        using (ITransaction tx = session.BeginTransaction())

        {

            //create a person

            Person p = new Person("Bruce", "Wayne");

            p.DateOfBirth = new DateTime(1972, 6, 2);

            p.HomePhone = "12345678";

            p.AltPhone = "987675123";

            p.Address.Line1 = "123 Bruce Manor";                   

            p.Address.State = "GT";

            p.Address.City = "Gotham";

            p.Address.Zip = "99999";

 

            //save the person

            session.Save(p);

 

            Assert.IsTrue(p.Id != 0, "Save should give p it's primary key");

 

            Person pVerify = (Person)session.Load(typeof(Person), p.Id);

            Assert.AreEqual(p, pVerify, "They weren't the same");

        }

    }

}

Here we create a new person object, save it to the database, then call our Load method (which we know works because of the previous test (TDD Purists won’t like this, but I haven’t seen an effective way to test this quickly).  Our Person objects (and subsequently, our Address objects) need to overrides the .Equals() method for the last assert to work.  As Rocky Lhotka says, let’s be good .NET citizens and override these methods in each of our objects.  Lastly, take notice that I’m using NHibernate’s transactions which get rolled back at the end of the test.  These don’t share the baggage of TransactionScope objects in the previous test.

This time we were able to create a mapping file for the Person object.  We learned to make sure and set it as an embedded resource so it is recognized by NHibernate.  Finally we learned some basic mapping concepts and backed them up with tests.

Next time we’ll introdude a few more objects and learn to map the relationships with NHibernate.

As promised, here is the current source code.  It contains all of the code written up to this article.  Comments and questions are encouraged.

 If you want to run the tests, you’ll need the NUnit Gui or the TestDriven.NET plugin for visual studio.

Credit Card Consolidation - Car Insurance - Share Dealing - Unsecured Loans