tags:

views:

224

answers:

2

Hi, just started out with NHIbernate and have one question, probably a bit of a stupi one! ;-) I have 2 tables, Email and Attachment, an email can have zero or more attachments. so I created a hbm file like this:

<set name="Attachments" table="Attachments">
  <key column="EmailId" foreign-key="fk_Attachments_Emails"/>
  <composite-element class="Foo.Emails.Attachment, Foo.Emails">
    <!-- PROBLEM HERE!!! -->
    <property name="Id" column="Id" type="long"  />          
    <!-- END PROBLEM -->
    <property name="Name" column="Name" type="String" length="50"/>
    <property name="Mime" column="MimeType" type="String" length="50"/>      
    <property name="Size" column="Size" type="long" />
    <property name="FilePath" column="FilePath" type="String" length="256"/>
    <property name="Parsed" column="Parsed" type="Boolean" />
  </composite-element>
</set>

As I want to be able to search for the attachments by PK (the Id column in the set) I included it, but now everytime I try to save an email with attachments I get an error from the db as Nhibernate tries to insert a value into the PK, which my db naturally wont allow.

So, my question is, can I extract the pk for the Attqachment table but stop Nhiberntate from writing it when inserting a an email/attachment? Should I swap to another container like ?? if so wold you be abler to provide an example as I struggling to find a one that I understand!

THanks for your help!

A: 

I think you want an bi-directional relationship. This way you can navigate the association both ways. This includes generated keys... Here is an example:

  <class name="Order" table="ORDERHEADER" lazy="false" >
<id name="OrderId" column="ORDERID" type="int">
  <generator class="sequence">
    <param name="sequence">"ORDERID_SEQ"</param>
  </generator>
</id>
<property name="OrderType" column="ORDERTYPE" type="Int16"/>
<bag name="OrderDetail" table="ORDERDETAIL" lazy="false" inverse="true">
  <key column="OrderId"/>
  <one-to-many class="OrderDetail"  />
</bag>

  <class name="OrderDetail" table="ORDERDETAIL" lazy="false">
<id name="OrderDetailId" column="ORDERDETAILID" type="int">
  <generator class="sequence">
    <param name="sequence">"ORDERDTLID_SEQ"</param>
  </generator>
</id>
<property name="OrderId" column="ORDERID" type="Int32"/>
<property name="ItemNumber" column="ITEMNUMBER" type="Int32"/>
<property name="OrderQuantity" column="ORDERQUANTITY" type="Int32"/>
<many-to-one name="Order" class="Order" column="OrderId" />

Adam Fyles
+1  A: 

Perhaps a more practical example? Where you have an object structure like this:

Email
--EmailId
--EmailProperty1
--AttachmentCollection

Attachment
--AttachmentId
--ParentEmail
--AttachmentProperty1

mapped to a table structure like this (not how i'd name it, but it's for example):

email
--emailId int PK, identity
--emailProp1 varchar(50)

emailattachment
--attachmentId int PK, identity
--emailId int, FK to email table
--attachmentProp1 varchar(50)

<hibernate-mapping>
        <class name="Email" table="email">
          <id name="EmailId">
            <!-- this tells NHibernate to use DB to generate id -->
            <generator class="native"/>
          </id>
          <property name="EmailProperty1" column="emailProp1"/>
          <bag name="AttachmentCollection" lazy="true" inverse="true">
            <key column="emailId"/>
            <one-to-many class="Foo.Emails.Attachment, Foo.Emails"/>
          </bag>
        </class>
        <class name="Attachment" table="emailattachment">
          <id name="AttachmentId">
            <generator class="native"/>
          </id>
          <property="AttachmentProperty1" column="attachmentProp1"/>
          <many-to-one name="ParentEmail" class="Foo.Emails.Email, Foo.Emails" lazy="proxy" column="emailId">
        </class>
    </hibernate-mapping>

In this map, you'd get the bi-directional relationship, and that generator tag is telling nhibernate that objects with a null Id property (you can also specify another "unsaved-value"), then you're inserting the object, else updating. Should fix your current problem.

Couple other things: examine closely what kind of containers you need to use when mapping (bag vs. set vs. list). There's an excellent writeup in hibernatingrhino's NHibernateFAQ.

Also, since you're new to NHibernate, I very, very greatly recommend the summer of nhibernate screencasts. The best tool I've found so far for learning.

joshua.ewer