Friday, December 08, 2006

Firebug 1.0 Beta released

The very handy Firebug javascript debugger for Firefox has just released a major update.  Click here to get it.

If you aren’t using Firebug, you’re missing out.  It is hands-down the best javascript debugger out there.

It can intercept and log all XMLHttpRequests, you can set breakpoints, inspect and modify the DOM, execute javascript on the fly with the console, and a lot more.  New features allow you to tweak and visualize CSS metrics (with rulers), and monitor network activity.

Seriously, what are you waiting for?  Go get it.

Monday, November 13, 2006

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

After a very long spell of inactivity, we’re back for Part 7 of the series!

Last time we left off with a decent domain model, a database, and the beginnings of NHibernate.

Since the last article, the NHibernate team has produced the ever-so-fantastic v1.2.0 beta 1.  This release supports numerous new exciting features.  Topping the list of cool new features is:  native support for .NET GenericsNative SQL 2005 is also supported.  Another feature was just enabled that will really help bridge the gap for those folks who will clutch to stored procedures forever:  Stored Procedure / Custom Query Support.

I’ll start today by slapping in this version of NHibernate and do a little bit of housekeeping.  With this new version of NHibernate, I no longer have a need for NHibernate.Generics (and thus I will remove it).  Some people might still use it, as it has the nice side-effect of automatically managing bi-directional relationships (which we’ll visit later), however I’m going to show this manually in this series.

I’ve changed my EntityList<T> / EntityRef<T> / EntitySet<T> to normal generic collections, and NHibernate will use them automatically.  These classes do provide you with an extra nifty feature (explained later), but it’s important to understand what it does under the hood, so I will implement the functionality the manual way, and later I’ll reference these classes to show how you might still want to use them.

So I’ve remove the old dll of NHibernate and I referenced in the new one.  I also updated my nhibernate schema file in Visual Studio so that I get the updated intellisense.  I compile, nothing is broken, and we’re ready to test!  The beauty of having our unit tests is that we have much more confidence that we know exactly what to fix, and we also know the instant that we are done fixing any breaking changes.  Our application returns to a known state of behavior very quickly.

Since I’ve made persistence level changes (the new NHibernate dll) as well as domain model changes (replacing NHibernate.Generics.Entity*<T> with standard .NET generic lists) I need to run both test assemblies.

 Here are the immediate results of the tests:

TestCase 'Flux88.Videocracy.Persistence.Tests.PersonTester.TestCanListPeople' failed: NHibernate.InvalidProxyTypeException : Type 'Flux88.Videocracy.DomainModel.Person' cannot be specified as proxy: method get_Id should be virtual
	c:\net\nhibernate-1.2.0.Beta1\nhibernate\src\NHibernate\Proxy\ProxyTypeValidator.cs(28,0): at NHibernate.Proxy.ProxyTypeValidator.Error(Type type, String reason)
	c:\net\nhibernate-1.2.0.Beta1\nhibernate\src\NHibernate\Proxy\ProxyTypeValidator.cs(76,0): at NHibernate.Proxy.ProxyTypeValidator.CheckMethodIsVirtual(Type type, MethodInfo method)
	c:\net\nhibernate-1.2.0.Beta1\nhibernate\src\NHibernate\Proxy\ProxyTypeValidator.cs(63,0): at NHibernate.Proxy.ProxyTypeValidator.CheckEveryPublicMemberIsVirtual(Type type)
	c:\net\nhibernate-1.2.0.Beta1\nhibernate\src\NHibernate\Proxy\ProxyTypeValidator.cs(22,0): at NHibernate.Proxy.ProxyTypeValidator.ValidateType(Type type)
	c:\net\nhibernate-1.2.0.Beta1\nhibernate\src\NHibernate\Cfg\Configuration.cs(915,0): at NHibernate.Cfg.Configuration.ValidateProxyInterface(PersistentClass persistentClass)
	c:\net\nhibernate-1.2.0.Beta1\nhibernate\src\NHibernate\Cfg\Configuration.cs(891,0): at NHibernate.Cfg.Configuration.Validate()
	c:\net\nhibernate-1.2.0.Beta1\nhibernate\src\NHibernate\Cfg\Configuration.cs(1035,0): at NHibernate.Cfg.Configuration.BuildSessionFactory()
	c:\sandbox\Videocracy\Flux88.Videocracy.Persistence\SessionSource.cs(55,0): at Flux88.Videocracy.Persistence.SessionSource.Initialize()
	c:\sandbox\Videocracy\Flux88.Videocracy.Persistence\SessionSource.cs(81,0): at Flux88.Videocracy.Persistence.SessionSource.GetSession()
	c:\sandbox\Videocracy\Flux88.Videocracy.Persistence.Tests\PersonTester.cs(27,0): at Flux88.Videocracy.Persistence.Tests.PersonTester.TestCanListPeople()

We have a few failing tests, however they all relate to the same problem.  NHibernate 1.2.0 beta 1 now sets everything to lazy-load by default.  This means that our objects must be able to be inherited so that NHibernate can inject proxy subclasses of our objects (the consumer doesn’t know or care that this happens).  To do this all of the methods and properties need to be virtual.   This is a large change, and it’s not something I entirely agree with, but it’s very easy to turn off.   (It pays to read the release notes of these 3rd party products!)  We’ll discuss how to effectively lazy-load a bit further on.

In our mapping file, we can specify default-lazy=”false” to override this behavior.  At a later time we may investigate and find that the class will benefit from lazy loading and we’ll revert it, but until then I’ll just make all the classes default-lazy=”false”.

Here’s the change:

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

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

                  namespace="Flux88.Videocracy.DomainModel"

                  assembly="Flux88.Videocracy.DomainModel"

                  default-lazy="false"

                  >

 

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

     …

  </class>

 

</hibernate-mapping>

Once that change is in place, all 5 of my persistence tests are passing.   I have 6 failing tests in my domain model, mostly due to my careless replacement of the EntityRef stuff with standard .NET collections.  The tests expose my oversights and once I fix them I’m back on track.

Ok, now where were we?  (It’s been a while, so I open NUnit and see that we have Save/List/Load for a Person object, but nothing else). We introduced some simple mapping concepts, and this time we’ll dig in a bit deeper.

How does NHibernate deal with associations?  Lets start with Account.  Account has a collection of Customer objects that represent its members.  In standard database terms, Account is a one-to-many with Customer.  How do we map this kind of relationship with NHibernate?

There are a few choices when looking at the documentation for NHibernate.  To understand them you must understand the semantics of each kind of list.  Ask yourself these questions:

  • is it one-to-one?  many-to-one?  many-to-many?
  • does order matter?
  • is it bidirectional?

From the NHibernate FAQ, we find this informative nugget, that explains the collections available to us (and their .NET counterparts):

  • The <list> maps directly to an IList.
  • The <map> maps directly to an IDictionary.
  • The <bag> maps to an IList. A <bag> does not completely comply with the IList interface because the Add() method is not guaranteed to return the correct index. An object can be added to a <bag> without initializing the IList. Make sure to either hide the IList from the consumers of your API or make it well documented.
  • The <set> maps to an Iesi.Collections.ISet. That interface is part of the Iesi.Collections assembly distributed with NHibernate.

Our Account -> Customer relationship is one-to-many.  I could choose to allow one customer to have many accounts, but I don’t see any real use for that yet.  Order does not matter either.  I could have 4 members on an account, and it doesn’t really matter what order they are given to my in a list. 

We also have to consider what each end of the association looks like.  Right now I’m looking at it from the perspective of Account, where Account has many Customers (members).  On the customer object, the customer only has one Account, so this isn’t a bidirectional association.  (We’ll see an example of this later).  Techically our collection maps to an ISet, but I’d rather not depend on the Iesi.Collections.dll, so I’m going to map it to a list (the only drawback is that the list will allow the same member twice, so I’ll just get around this in our model manually).

Here’s how we’ll deal with that:

/// <summary>

/// Adds a member to this account

/// </summary>

/// <param name="customer"></param>

public void AddMember(Customer customer)

{

    //ignore multiple adds for the same customer.

    if(_members.Contains(customer)) return;

 

    _members.Add(customer);

 

    //make sure that our association is handled on both sides

    customer.Account = this;

}

 

/// <summary>

/// Removes a member from this account.

/// </summary>

/// <param name="customer"></param>

public void RemoveMember(Customer customer)

{

    //ignore the call if the customer isn't a member of this account

    if (!_members.Contains(customer)) return;

 

    _members.Remove(customer);

 

    //make sure that our association is handled on both sides

    customer.Account = null;

}

 The rest of the class is self-explanatory, so I won’t include it here.  You’ll  be able to download the project at the end of today’s article, however.

Next up is the mapping.  Let’s take another look at the table structure for reference:

CropperCapture[4]

This is slightly different than what was in the last archive.  Instead of an account having a single primary customer, any customer can be the ‘Owner’ of his/her account.  I chose to keep the association simple for this demo.  I also wanted to allow multiple ‘Owners’ for a single account.  I’ve updated the tests to reflect this change.

Here you see that many customers belong to exactly one account.    This is a one-to-many relationship from Account to Customer.

If we stop and think about the domain for a minute, we can determine that the Customer will be identified first (by his/her ID or Account #) and that needs to be able to pull up the account.  I’d also like to keep this relationship bidirectional.  That means that I need to map the relationship on both classes so that we can do this:

customer.Account ….  

or this:

for each Customer c in _account.Members { … }

Here is the relevant mapping for Customer:

 <!-- CUSTOMER  -->

 <joined-subclass name="Customer" table="Customers">

  <key column="PersonId" />

 

  <!-- todo:  map this to an enumeration -->

  <property name="RentalRestriction" type="Int32" column="rentalRestrictionId" />

 

  <many-to-one name="Account" class="Account" column="accountId" cascade="save-update" />

 

 </joined-subclass>

This tells NHibernate that this is the *many* end of a one-to-many association.  We tell it the property name, type, foreign key column name, and our cascade strategy.  This basically means, whenever we save or update our Customer, cascade the save/update to the Account as well.  You can also specify to cascade deletes as well if you need to.

The Account mapping looks like this:

 <class name="Account" table="Accounts" where="Active=1">

 

    <!-- ... -->

 

    <bag name="Members" access="nosetter.camelcase-underscore" lazy="true" 
         
cascade="save-update" inverse="true">

         <!-- this key refers to the Account key in the Customer table -->

         <key column="accountId" />

         <one-to-many class="Customer" />     

    </bag>

 

 </class>

This section tells NHibernate to map this association as a bag.  Lazy=true means that the collection will only actually be retrieved from the database once it is accessed.  NHibernate does this by silently replacing our IList with a proxy that knows about the session and how to hydrate the collection.  This is 100% transparent to our consumers, so make sure you are using this in appropriate places.  Lazy=false will force NHibernate to pre-load the entire association (and it’s associations(and it’s associations(…. you get the point…))). 

To test that this association worked, I wrote a simple test:

 [Test]

 public void CanSaveCustomerAndAccount()

 {

    Customer c = TestHelper.GetTestCustomer();

 

    Account a = new Account();

    a.AddMember(c);

 

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

    {

        using (ITransaction tx = session.BeginTransaction())

        {

            session.SaveOrUpdate(c);

            session.Flush();

 

            session.Evict(c); //make sure we don't get an object from the cache

 

            Assert.AreNotEqual(0, c.Id, "Customer didn't get an Id after save");

            Assert.AreNotEqual(0, a.Id, "Account didn't get an Id after save");

 

            Customer customerFromDb = session.Get<Customer>(c.Id);

 

            Assert.AreNotSame(c, customerFromDb, "Got same instance of customer!");

            Assert.AreEqual(a, customerFromDb.Account, "Account didn't get saved");

 

            tx.Rollback();

        }

    }

 }

This test is passing and we have our first association mapped!

I think this is a good stopping point.   We have migrated our version of NHibernate and our tests forced us to fix any outstanding issues before continuing.  We also identified our first association, mapped it, and tested it.

From here on out I will step up the pace and start glossing over the details a bit and focus on getting working product done using this domain model.  As I begin writing some UI components I will come across some features I have not developed, which may require more mapping changes and tests.  In order to finish this series sometime this year I’ll be speeding up a bit.  I will still continue to post the source so that you may follow along.  If you have comments or questions, feel free to comment.

Here is the latest source:

File Attachment: Videocracy_07.zip (44 KB)

Agile Houston - Finally!

I was very excited to hear the creation of the first Houston Agility User Group, Agile Houston.

If you are interested in Agile practices and methodologies and live in the Houston area, I encourage you to join the group and attend the first meeting!

Currently I expect the first meeting to occur sometime in January, so as soon as I find out a definite date, I’ll post it here.

Wednesday, October 18, 2006

TulsaTechFest 2006 was a Blast

I attended TulsaTechFest 2006 this past weekend and I had a fantastic time.  I was able to meet a number of interesting people and learned quite a bit.

I attended…

  • NUnit Extensibility with Tim Rayburn
    Tim is an incredibly passionate guy.  He didn’t have quite enough time to fully cover his presentation, though I did learn from it.  He ended up spending about 15 minutes of it just pimping CodeRush.
  • IoC / DI with Dru Sellers
    Inversion of Control / Dependency Injection has been an interest of mine for some time now, but it’s a tad difficult to wrap your head around how it actually works.  In theory I understood it, but with Dru’s explanation I am now fully onboard with it and will definitely start utilizing it in my projects at home to get better at it.  Dru was very excited about it and it showed.  His talk was very casual and informative.
  • POCOS In Action with Dru Sellers
    POCOs, or Plain Old CLR Objects, is a concept adopted from Java (you guessed it: POJOs) which is basically a move away from Entity Java Beans.  The gist of it is that we’d like to focus on simple objects that express our domain model and business rules and nothing else.  No infrastructure mixed in with our logic.  No persistence related concerns embedded in our objects.  This talk was very high level and actually blended with IoC and NHibernate, so I wish I would have attended another talk.  Dru did a great job explaining the POCO mentality and I know he made a great impact on my buddy Tom, a Java developer.
  • NHibernate with Dru Sellers (see a pattern?)
    I attended this talk mainly to show the flag, as I knew it would be more of an introductory overview.  The audience seemed genuinely interested in the subject and Dru explained it well.  I also contributed my two cents and I hope I wasn’t intruding .
  • The Science of Great UI with Mark Miller
    UI Design is a big interest of mine, but the fact that Mark Miller was presenting sealed the deal on this talk.  Mark is crazy, and if you haven’t listened to him on Mondays or Millahseconds, you really should.  He’s insanely hilarious and I thoroughly enjoyed his presentation.  My favorite part of this presentation was when Mark shoved his kid off of his lap to take a picture of a “horribly conceived modal dialog box ever” in a Lego game he was playing with his kids.  I can totally see him doing that.
  • Component-based Architectures with Mark Miller
    This talk was about to get very interesting when Mark ran out of time.  Some of us were a bit confused on where he was going, and we talked to him about it afterwards and he was eager to hear the feedback.  Basically he argued that in order to gain the best competitive advantage, we as developers should focus on implementing new features faster, (features and time being two out of 4–5 aspects of a product that we control) and to do that we have to understand how difficult it is for new developers to just get work done.  He argued that the less visible structure that your code has, the easier it is to add new features.  Mark is a fan of building components (yes, like the ones you drag onto a component surface in visual studio).  If you aren’t clicking with this yet, and I fully understand why, then you should go try to create a plug-in with Visual Studio and see if you can get a simple one completed.  Then go try it with the free DXCore and see if you aren’t blown away at its simplicity.

I also won a book, Professional Ajax (WROX) which is now 8th on my reading list.

After the event I met up with Tim Gifford and Javier Lozano, and we went to an Irish pub and later mosied on down to Arnie’s to where Microsoft was buying drinks!  I met up with Shaun Walker (from DNN fame) there and I made sure to give him a hard time about his picture.   Sorry Shaun, no hard feelings!  (He’s really a cool guy).  At the bar we enjoyed some tech conversation and jager bombs (ouch) and had a good time.

I can’t wait to go again next year.

Sunday, October 08, 2006

Tulsa Tech Fest

I’ll be attending Tulsa Tech Fest this weekend.

I’m excited to see quite a few people speak, including:

  • Markus Egger
  • Mark Miller
  • Carl Franklin
  • Dru Sellers
  • Bill Vaughn

However I was saddened to hear that Jean-Paul Boodhoo will not be speaking anymore.  I was mostly excited about his sessions on Continuous Integration and Mock-Objects.  Ah well, I’ll catch him next time around.

I haven’t finalized my schedule yet, but I’m looking forward to some of the Agile sessions, some Ajax, some WPF, and general architecture.  I’ll post my schedule later on, if anyone wants to meet up.

Is anything going on after the event?

Friday, October 06, 2006

Compiled vs Dynamic Laguages and the Code Feedback Loop

So I bit the bullet and installed Ruby on Rails.  I’ve been reading a lot about Ruby (mainly blogs) and decided that it’s about time to learn another language.  The Pragmatic Programmers believe that you should dedicate some time to learn a new language every year.

My first impressions are probably pretty common.  Ruby is not easy to jump into.  They have a lot of great information on the internet, but I found that things didn’t go as smoothly as I had hoped.  This is probably due to the fact that there are major changes between each version of ruby/rails, and there are old tutorials directed at older versions of Ruby or Rails.

The second hinderance I found was that, with Ruby (among other dynamic languages), you don’t get any intellisense.  Being brought up with Visual Studio made me spoiled, I suppose.  The fact is, with any dynamic language, such as Ruby, Python, or Javascript…  Intellisense is difficult to provide.  Type information often isn’t available until runtime.

This really annoyed me at first, and I was quick to dismiss dynamic languages. 

Intellisense really makes your learning experience much easier.  When I started in .NET, I had a few books, but mainly I just used Intellisense to navigate my way around the framework.  If you didn’t know how to send email with .NET, you could easily just type System.Web.Mail. and you’d see the relevant classes involved.  Intellisense is an extremely effective discoverability tool.  

Now that I am an experienced .NET developer, I know all of these things by heart.  There’s not much stopping me from writing my programs in Notepad2.  I don’t rely as heavily on Intellisense like I did before.  I still use Visual Studio, though, because having your compiler and debugger integrated with your editor is almost a necessity.

This isn’t the case with dynamic languages.  You write a program (often times in a single file with FAR fewer lines of code) and you run it.  That’s it.  There’s no compilation or startup time.  You get your results right there.  If you mispell a type or call a method on the wrong class of course you’ll get an error.  But you find this out sooner that your C# / Java program will compile.  If you can write 5 lines of code and push a button to see if it worked…  without waiting for a compiler or debugger, then your code-feedback-loop is MUCH tighter.  Agile principles thrive on having small feedback loops.  This is (in my opinion) the single largest reason why Agile is so effective.

The compiler is becoming less and less popular these days because it cannot protect your program from logic flaws.  It’s becoming much like the spell-check feature of word processors.  They can tell you that you mispelled the word definate definite, but a sentence like this one will pass spell-check just fine:  We will meat at the movie theater.  A compiler can only take you so far.  To verify your program works, you have to compile it, run it, navigate to the section, and test it.  In a dynamic language, half of these steps are removed, leaving you with a much tighter code-feedback-loop.

We all love intellisense (and I will welcome it for Ruby with open-arms), but don’t let that stop you from writing your next small program in a language like Python or Ruby.  It will give you another tool in your developer toolbox and make you a better programmer in *any* language.

 

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.

Homeowner Loan - New York Hotel - Savings Accounts - Secured Loans