More than one time, in my courses, in this blog and in various NH’s users list, I talked about a rule of thumb about mappings: not try to be clear because it obscures.
Have a look to this mapping:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="YourApp.Common.DataObjects.Address, YourApp"
table="Address">
<id name="Id" type="Int32" unsaved-value="null">
<column name="Id"
length="4" sql-type="int"
not-null="true" unique="true" index="PK_Address"/>
<generator class="native" />
</id>
<property name="Address1" type="String">
<column name="Address1" length="255"
sql-type="varchar" not-null="true"/>
</property>
<property name="Address2" type="String">
<column name="Address2" length="255"
sql-type="varchar" not-null="false"/>
</property>
<property name="City" type="String">
<column name="City" length="255"
sql-type="varchar" not-null="true"/>
</property>
<property name="State" type="String">
<column name="`State`" length="2"
sql-type="varchar" not-null="true"/>
</property>
<property name="Zip" type="String">
<column name="Zip" length="12"
sql-type="varchar" not-null="true"/>
</property>
<many-to-one name="Contact" class="YourApp.Common.DataObjects.Contact, YourApp">
<column name="Contact_Id" length="4"
sql-type="int" not-null="false"/>
</many-to-one>
<bag name="BillToOrderHeaders" inverse="true" lazy="true" cascade="all-delete-orphan">
<key column="BillToAddress_Id"/>
<one-to-many
class="YourApp.Common.DataObjects.OrderHeader, YourApp"/>
</bag>
<bag name="ShipToOrderHeaders" inverse="true" lazy="true" cascade="all-delete-orphan">
<key column="ShipToAddress_Id"/>
<one-to-many
class="YourApp.Common.DataObjects.OrderHeader, YourApp"/>
</bag>
</class>
</hibernate-mapping>
This is how it may look having the same result:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"In this second representation we can understand immediately which are the difference with the NHibernate convention and, over all, you are not hurting your eyes reading it ;-) .
assembly="YourApp"
namespace="YourApp.Common.DataObjects">
<class name="Address">
<id name="Id">
<generator class="native" />
</id>
<property name="Address1" not-null="true" />
<property name="Address2"/>
<property name="City" not-null="true"/>
<property name="State" length="2" not-null="true"/>
<property name="Zip" length="12" not-null="true"/>
<many-to-one name="Contact" column="Contact_Id"/>
<bag name="BillToOrderHeaders" inverse="true" cascade="all-delete-orphan">
<key column="BillToAddress_Id"/>
<one-to-many class="OrderHeader"/>
</bag>
<bag name="ShipToOrderHeaders" inverse="true" cascade="all-delete-orphan">
<key column="ShipToAddress_Id"/>
<one-to-many class="OrderHeader"/>
</bag>
</class>
</hibernate-mapping>
I've just a two month experience studying NHibernate, and I've always found your notes and suggestions very helpful.
ReplyDeleteYet this time I disagree: when I look at my mapping file, I want to get all possible information about the underlying database, and it's easier (for me) to read them in this file than to remember NH conventions and defaults.
But... you know, I'm just a NH newbie ;)
Exactly as beginner you should write less as possible in the mapping.
ReplyDeleteThe mapping is "the language to program NH": less code less bug.
I suppose the developer of the original mapping just wanted to be explicit and be on the safe side if convention is going to change in version Next+N.
ReplyDeleteAbsolutely 100% yes!
ReplyDeleteI'd like to add this for those of you who use the mapping to tell you the schema of the database:
A mapping like the first one above only tells you what *should* be in your database. This is not useful information. You should be concerned with what *is* in your database.