Browsing Posts published in November, 2007

Thanks to everyone who attended my Ignite Your Coding webcast. I enjoyed sharing a small sampling of the wealth of tools available for the Windows and .NET developer. For those of you who missed the webcast (or would like to watch it again), it’s available on-demand here.

Below you will find a list of links that I mentioned during the webcast as well as a few attendee-contributed suggestions:

Resources

Community-Contributed Resources (During the Webcast)

Be sure to check out the rest of the Ignite Your Coding webcast series as there are some other great sessions there.

In a domain model, you will sometimes encounter immutable data - objects that can only be read from a database, but never modified. The question is how to test your persistence layer to ensure that you can read them. One way is to hard code values into your tests and assume that the appropriate rows are in the database. This is rather fragile as you are counting on your database being in a known good state. This also prevents you (or another developer) from getting latest from source control onto a clean developer workstation and being able to run the unit tests immediately. You must populate a test database with known good data first. Here’s a little trick you can play with NHibernate. Let’s say you have the following class:

namespace JamesKovacs.Examples.ImmutableData {
    public class Invoice {
        private readonly int m_Id = 0;
        private readonly string m_InvoiceNumber;
        private readonly decimal m_Amount;
        private readonly DateTime m_InvoiceDate;

        public Invoice() {
        }

        public Invoice(string invoiceNumber, decimal amount, DateTime invoiceDate) {
            m_Amount = amount;
            m_InvoiceDate = invoiceDate;
            m_InvoiceNumber = invoiceNumber;
        }

        public int Id {
            get { return m_Id; }
        }

        public string InvoiceNumber {
            get { return m_InvoiceNumber; }
        }

        public DateTime InvoiceDate {
            get { return m_InvoiceDate; }
        }

        public decimal Amount {
            get { return m_Amount; }
        }
    }
}

And its corresponding NHibernate mapping file:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   namespace="JamesKovacs.Examples.ImmutableData"
                   assembly="JamesKovacs.Examples.ImmutableData"
                   default-access="field.pascalcase-m-underscore">
  <class name="Invoice" mutable="false">
    <id name="Id">
      <generator class="native" />
    </id>
    <property name="InvoiceNumber"/>
    <property name="Amount"/>
    <property name="InvoiceDate"/>
  </class>
</hibernate-mapping>

Note that the Invoice is lookup data only. So it is declared as immutable in the mapping file (mutable=”false”). NHibernate will not permit INSERT, UPDATE, or DELETE operations against the entity. The question is how do we test this? We could circumvent NHibernate and directly insert test data into the table via ADO.NET. The downside is that you’re coupling your test data generation code to a particular database schema. If the database schema changes, you must not only update the NHibernate mapping, but you must also modify your SQL statements for creating test data. A definite violation of DRY (Don’t Repeat Yourself) Principle. Let’s see if there is a better way…

NHibernate can generate the database schema from mapping files using NHibernate.Tool.hbm2ddl.SchemaExport. The problem is that you can’t insert data into the Invoice table since the type is mapped as immutable. However, you can read the NHibernate configuration and mapping files and modify the mapping at runtime. This is done by cfg.GetClassMapping(typeof(Invoice)).IsMutable = true. We’re switching our immutable entity to a mutable one on the fly for the purposes of populating test data! Note that you have to modify the mapping before creating your SessionFactory.

using System;
using JamesKovacs.Examples.ImmutableData;
using MbUnit.Framework;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;

namespace JamesKovacs.Examples.ImmutableData.Tests {
    [TestFixture]
    public class InvoiceRepositoryTests {
        private const string InvoiceNumber = "ABCD1234";
        // N.B. You should do this once before all your repository tests
        //      as creating a SessionFactory and executing DDL is time-consuming.
       [SetUp]
        public void Setup() {
            Configuration cfg = new Configuration().Configure();
            SchemaExport exporter = new SchemaExport(cfg);
            exporter.Execute(false, true, false, false);
            cfg.GetClassMapping(typeof(Invoice)).IsMutable = true;
            ISessionFactory sessionFactory = cfg.BuildSessionFactory();
            using(ISession session = sessionFactory.OpenSession()) {
                session.BeginTransaction();
                Invoice invoice = new Invoice(InvoiceNumber, 42m, DateTime.Today);
                session.Save(invoice);
                session.Transaction.Commit();
            }
        }

        [Test]
        public void CanRetrieveInvoice() {
            using(UnitOfWork.Start()) {
                IInvoiceRepository repo = new InvoiceRepository();
                Invoice invoice = repo.FindByInvoiceNumber(InvoiceNumber);
                Assert.IsNotNull(invoice);
                Assert.AreEqual(InvoiceNumber, invoice.InvoiceNumber);
            }
        }
    }
}

So we now have an elegant solution for populating immutable test data in a clean database without resorting to hand-coded SQL.

N.B. UnitOfWork.Start() sets up an NHibernate session that is used internally by the repositories. It is based on Oren Eini’s UnitOfWork implementation in Rhino Commons.

MSDN Canada is presenting a weekly webcast series called Ignite Your Coding starting Tuesday, November 6, 2007. I will be presenting the second webcast in the series on Tuesday, November 13, 2007 from :

Frameworks and Tools for the Windows Developer

Numerous frameworks and tools exist to help developers be more productive when building applications on Windows. In this session, you’ll discover some indispensable tools that will enable you to be a more effective developer of Windows. Expand your toolset by learning what’s available today!

Register now!

Here is the full line-up of webcasts. Further details and registration for the other webcasts can be found on the Ignite Your Coding website.

November 6 Understanding the Windows – Based Development Platform
November 13 Frameworks and Tools for the Windows Developer
November 20 Security Essentials for Windows
November 27 The Art of Debugging in Windows
December 4 Application Deployment on Windows
December 11 Developing as a Non-Admin

Here are the code samples from some recent presentations…

Alberta Architect Forum 2007 – Creating Flexible Software

Austin .NET User Group – The NHibernate Mafia and the Persistent Ignorant Domain Model

Edmonton Code Camp 2007 – Building Applications Using ALT.NET

Thanks to everyone for attending the sessions, asking questions, and providing feedback.