I have some web methods that return my objects back as serialized XML. It is only serializing the NHibernate-mapped properties of the object... anyone have some insight? It seems to be that the web methods are actually serializing the NHibernate proxies instead of my classes. I've tried using [XMLInclude] and [XMLElement], but the properties are still not serializing. I have a really horrible hackish way of getting around this, but I wondered if there was a better way!
Something like this:
<?xml version="1.0" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="StoryManager" assembly="StoryManager">
<class name="Graphic" table="graphics" lazy="false">
<id name="Id" column="id" type="int" unsaved-value="0" >
<generator class="identity"/>
</id>
<property name="Assigned" />
<property name="Due" />
<property name="Completed" />
<property name="UglyHack" insert="false" update="false" />
<many-to-one name="Parent" class="Story" column="story_id"/>
</class>
</hibernate-mapping>
public class Graphic
{
private int m_id;
public virtual int Id
{
get { return m_id; }
set { m_id = value; }
}
private DateTime? m_assigned;
public virtual DateTime? Assigned
{
get { return m_assigned; }
set { m_assigned = value; }
}
private DateTime? m_due;
public virtual DateTime? Due
{
get { return m_due; }
set { m_due = value; }
}
private DateTime? m_completed;
public virtual DateTime? Completed
{
get { return m_completed; }
set { m_completed = value; }
}
public bool UglyHack
{
get { return m_due < m_completed; } // return something besides a real mapped variable
set {} // trick NHibernate into thinking it's doing something
}
}
This is obviously no way to write code. If I don't have the "fake" mapping in there (UglyHack property), that property won't be serialized. For now I'm looking into using (Data) Transfer Objects, and may be on to something using reflection...
The best way to serialize the NH mapped object is to not serialize it :).
If you're sending it across the wire you should really create a DTO for it. If you don't want to create that object you can set [XmlIgnore] on properties you don't want serialized.
If you want all properties, you have to load them ALL from the database - for some an eager load will be enough for others(where too many joins will start duplicating data) you'll have to access that property in any way you want to trigger the load.
Edit:
And I'd like to add another thing - sending your domain entities over the wire is always a bad idea. In my case I learned it the hard way - I expose some entities over a WebService - and now almost any change(rename a property, remove a property ..etc ) to my domain kills the app using the WS - plus a whole bunch of properties have [XmlIgnore] on them ( don't forget about circular dependencies).
We'll do a rewrite soon enough - but rest assure that's not something I'll ever do again. :)
Edit 2
You could use AutoMapper for transferring the data from your entity to the DTO. They have some examples on the site.