Thursday, May 28, 2009

NHibernate| many-to-many

So I’m starting to build a proof of concept product catalog as both a reason to use NHibernate in a “real world” application but also to apply ASP.Net MVC with it as well. I chose both of these technologies because they’re supposed to create strongly built applications faster.

The following data model is the start of the catalog with more being added over the next few weeks.



The tags collection on the Product is simply an ISet<Tag>. I’ve used this rather than a list because I want to have a distinct set of tags per product. Here’s the mapping for both entities.

<class name="Product">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>
  <property name="ShortName"/>
  <property name="ItemId" />
  <property name="Sku" />
  <property name="Wholesale" />
  <property name="Retail" />
  <property name="ImageUrl" />
  <property name="IsActive" />
  <set name="Tags" table="TagAssociations" cascade="all" >
    <key column="productId"/>
    <many-to-many column="tagId" class="Tag" />
  </set>
</class>

<class name="Tag">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name" unique="true"/>
</class>


Notice we’ve created an interim table to join the Tags and Products called TagAssociations (there are probably better names but meh) and done this through a many-to-many relationship on the Tags property binding it to Tag objects through the table.


From here on out our interactions with TagAssocations is nil. For example pulling products by Tag only requires the following code.


public IList<Product> GetByTag(Tag tag)
{
  using (ISession session = NHibernateHelper.OpenSession())
  {
    var list = session
      .CreateCriteria(typeof(Product), "p")
      .CreateCriteria("Tags")
      .Add(Restrictions.Eq("Id", tag.Id));
    return list.List<Product>();
  }
}


Because we’re adding in our property Tags through CreateCriteria and saying we want to pull that by Id the following TSQL is generated automatically.

SELECT this_.Id as Id3_1_, this_.Name as Name3_1_, this_.ShortName as ShortName3_1_, this_.ItemId as ItemId3_1_, this_.Sku as Sku3_1_, this_.Wholesale as Wholesale3_1_, this_.Retail as Retail3_1_, this_.ImageUrl as ImageUrl3_1_, this_.IsActive as IsActive3_1_, tags3_.productId as productId, tag1_.Id as tagId, tag1_.Id as Id5_0_, tag1_.Name as Name5_0_
FROM Product this_
inner join TagAssociations tags3_ on this_.Id=tags3_.productId inner join Tag tag1_ on tags3_.tagId=tag1_.Id
WHERE tag1_.Id = @p0; @p0 = '1'


To me this is a miracle to behold considering the shear amount of work this would take under normal circumstances.

Wednesday, May 27, 2009

NHibernate and Micrsoft Team Test

I couldn’t find much information on using Microsoft’s Team Test Suite and NHibernate so here’s the condensed version so you don’t have to have the same issues I went through.

If you use the “Getting Started” guide here and substitute Microsoft’s test suite for NUnit add the following attributes just below the [TestClass] attribute on the class definition.  Remember to substitute your database’s name in for [Database Name].

[DeploymentItem("hibernate.cfg.xml")]
[DeploymentItem("[Database Name].sdf")]

This will tell the test suite these are dependencies and to deploy them to the TestResults folder where the tests are run.

Voila!  Everything “should” run as advertised but remember to place these on every single test fixture you create.  Its a bit of a pain and I hope Microsoft can fix this in either a service pack of Visual Studio or in the next version.

Monday, May 18, 2009

Crow

I swear I would never see he day in which I found something that Java does better than the .Net framework.  Unfortunately for me today is that day.  I usually don’t do Java very much because my job never calls for it and I have zero *umph* to take and learn the antiquated language and yet today as I’m working in Java for a class I learned something I’m very very jealous of that Java supports and .Net does not.  Anonymous instances of interfaces.

Anyone who’s done a UI in Java has done this 1,000,000,000,000,000 times so if this is something of a “duh dumbass” moment as you read this go ahead and pass on by otherwise here is what I have.

Java events work extremely different that .Nets do.  They have this concept of listeners in which one creates an object that implements the interface ActionListener and a method is nailed down on the fly such as the following code specifies. 

btnCalculate.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Calculate(e);
            }
        });

Notice that we’re adding the ActionListener to the JButton btnCalculate and the method is being defined on the fly.  In the .Net world we have similar feats for Events and anonymous types, but generally speaking we can’t say this anonymous type is of type INotifyValueChanged and pass in a dynamic object that maps the interface as is done here in Java.

I’m envious of this because it would be such a useful construct for a host of uses including but not limited to proxy objects used in TDD.

I would like also to state that the object works as a closure due to the fact that information contained in the actionPerformed method has access to everything it’s host object does. 

I imagine Java geeks use this technique often and are rolling over in their Javaesque graves right now seeing that a .Net guy is envious of such a thing but credit is due where credit is due and this is just cool.  Come on CLR team give me this!