Saturday, October 29, 2005

NHibernate PropertyAccesException

Like many things in NHibernate, causes of the PropertyAccessException aren’t particularly well documented.  (Well, they may be documented somewhere, but dang if I can find much on it.)  My NUnit tests were throwing this error during relationship tests with the “amplifying” message that the properties I was using for ID values weren’t the correct type. 

Huh?  Single entity stores were working just ducky, but trying to work with many-to-many relationships was failing.  The many-to-many definitions in the hbm.xml map files were all fine — trust me, I double-checked them about eight million times last night between 11pm and 1am when I finally quit last night.

This morning I finally found a Google hit that pointed me in the right direction: incorrect storage of the referenced entity, causing a null value in a member of type “Int32”.  You have to be sure you correctly set your collection properties in both sides of a relationship you’re trying to store via NHibernate.  It turns out I was incorrectly setting a collection on one side of my relationship.

Here’s the working (but not optimized) code:

[Test]

public void CheckAddPersonWithOneType()

{

PersonEntity personToDB = tep.MakeDefaultPersonEntity();

//Add the Person to the PersonType object's collection

speakerType.Persons.Add(personToDB);

//Add the PersonType to the Person object's collection

personToDB.PersonTypes.Add(speakerType);

IDal<PersonEntity> pda = new PersonDA();

int storedID = (int)pda.AddEntity(personToDB);

PersonEntity fromDB = pda.GetEntity(storedID);

IList retTypes = new ArrayList(fromDB.PersonTypes);

foreach (PersonTypeEntity type in personToDB.PersonTypes)

{

Assert.IsTrue(retTypes.Contains(type));

}

//clean up list

speakerType.Persons.Remove(personToDB);

}

 The all important lines are here:

//Add the Person to the PersonType object's collection

speakerType.Persons.Add(personToDB);

//Add the PersonType to the Person object's collection

personToDB.PersonTypes.Add(speakerType);

speakerType is one end of the relationship, persontoDB is the other.  Persons and PersonTypes are the collections holding the other end of the relationship.

Remeber that this is a many-to-many relationship?  Remember that m-m relationships need a link table between the two entities?  What’s cool about NHibernate is that I don’t have to fool at all with storing stuff in that link table.  NHibernate handles all that for me when I store the entities with one statement:

int storedID = (int)pda.AddEntity(personToDB);

Way cool.

NHibernate’s learning curve (and #%*@!! documentation) is tough going, but I think I’m going to like things once I get up to the next plateau.  I’m also weary of trying to wade through examples which aren’t much help.  Hopefully I’ll be able to put up some clear examples once I get things working well and refactored for clarity.

Now Playing: Guster — Lost and Gone Forever.  I’ve been playing a lot of Guster and Coldplay lately.  Well, a lot of other stuff, too, plus Springsteen’s The Rising seems to be stuck in my audio stream for some reason.  In any case, I really dig the cool harmonies and melodies.  Plus the lyrics are pretty thoughtful.  (Unlike The Mavericks, who I love but seem to be of the Gene Autry school of  All My Songs Have Five Words.)

No comments:

Post a Comment