Nhibernate – property with formula (concl.)

Entities:

—————————————————————————–

public class Order

{

public int OrderID { get; set; }

public string CustomerID { get; set; }

public Shipper ShipVia { get; set; }

}

 

public class Shipper : ILifecycle

{

public int ShipperID { get; set; }

public string CompanyName { get; set; }

public string Phone { get; set; }

#region ILifecycle Members

public LifecycleVeto OnDelete(NHibernate.ISession s)

{

throw new NotImplementedException();

}

public void OnLoad(NHibernate.ISession s, object id)

{

}

public LifecycleVeto OnSave(NHibernate.ISession s)

{

throw new NotImplementedException();

}

public LifecycleVeto OnUpdate(NHibernate.ISession s)

{

throw new NotImplementedException();

}

#endregion

}

—————————————————————————–

 

And finally the SQL function:

—————————————————————————–

ALTER FUNCTION dbo.GetShipper(@shipperId int)

RETURNS int

AS

BEGIN

RETURN @shipperId

END

—————————————————————————–

 

Obviously, you’ll want the function to do something meaningful, but the idea is you return the PK for the entity.

 

 

As it turns out specifying the property type is not enough, we have to do something else to get the NHibernate to recognize our type. That came as surprise for me, considering documentation makes no mention of it.

 

I had to step through the NHibernate code to see that it tried to obtain an instance of IType given our type name.

 

First path I tried was making the class [Serializable], as I recall that our types at the project where it "just worked for me" were all [Serializable]. In short – It doesn’t work.

 

The trick it turned out is in ILifecycle interface. We had that interface implemented from the earlier days of NHibernate.

Today the interface is considered too intrusive (which it is) and judging from the NHibernate source code, nothing better has been implemented. So I think it’s a bug, or at least something that should be mentioned in the documentation explicitly.

 

Anyways, as you can see implementation of ILifecycle can be trivial, you just have to make sure you don’t veto anything. So if you don’t mind getting your domain model "dirty" that’s the simpliest way to get it working.

 

Nhibernate – property with formula (concl.)

Nhibernate – property with formula (cont.)

First, I have to split this post in 2, becuase Spaces can’t handle 2 pages of text in one post. I really have to switch to some other means of blogging…

 

Anyways, I received a request for a sample of formula mapping and since I wasn’t any longer with the company/project where I noticed this behaviour I decided to implement if "from scratch" – using NHibernate from the SVN trunk, Northwind and C# 3.0 (why not?).

 

It turned into quite an exercise, but long story short: it’s not as simple and not as nice as I thought.

Here’s the final code example:

Mapping:

—————————————————————————–

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">

<class name="PropertyFormulaExample.Shipper, PropertyFormulaExample" table="Shippers" lazy="false" >

<id name="ShipperID" column="ShipperID" unsaved-value="0">

<generator class="native" />

</id>

<property name="CompanyName" column="CompanyName" />

<property name="Phone" column="Phone" />

</class>

</hibernate-mapping>

 

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">

<class name="PropertyFormulaExample.Order, PropertyFormulaExample" table="Orders" lazy="false">

<id name="OrderID" column="OrderID" unsaved-value="0">

            <generator class="native" />

</id>

<property name="CustomerID" column="CustomerID" />

<property name="ShipVia" type="PropertyFormulaExample.Shipper, PropertyFormulaExample" formula="dbo.GetShipper(shipvia)" />

</class>

</hibernate-mapping>

—————————————————————————–

 

(to  be continued …)

 

Nhibernate – property with formula (cont.)

Nhibernate – property with formula

UPDATE (July ’08)
Every localized google in the world (.de, .fr, etc) is attracting hits on this page with "nhibernate+formula+property" so I thought I’d post a few links.
 

UPDATE (May ’08):

Lots of hits on this page, so I’ve expanded on the topic:
Nhibernate – property with formula

Nhibernate: using ‘formula’ to map to a class

On one of the projects I work on I came across the need to use a function to calculate a property value.
 
The basic functionality is well documented in the online docs, however it doesn’t explicitly say what happens if the function returns DB PK (id) and you want it mapped to a class. It’s not even matter of "formula" as it is general matter of mapping.
 
Normally mapping to a class is done with <many-to-one> element, but that element doesn’t support "formula" attribute, nor does it have <loader> element.
Simple test shows that it works if you simply specify the "formula" and the "type" attributes. Apparently it works almost like many-to-one, with one notable difference: if value is null, many-to-one assigns null, while property seems to assign a new uninitialized instance. I can live with that.
 
All hail nhibernate!

 

Nhibernate: using ‘formula’ to map to a class