Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate One-To-One Mapping

I'm new to NHibernate so have had limited exposure to mappings etc so far, and I've just hit a scenario which I need some help with.

I have 2 tables:

Reviews TaggedReviews

I have 2 classes that look like this (I've excluded non-important properties for brevity):

Review

public virtual int ReviewId { get; set; }
public virtual TaggedReview TaggedReview { get; set; }
public virtual string Title { get; set; }
public virtual string Descrip { get; set; }

TaggedReview

public virtual int ReviewId { get; set; }
public virtual Review Review { get; set; }
public virtual string TaggedReviewDescrip { get; set; }

My NHibernate XML mapping files for these tables/classes are currently as follows (edited for brevity):

Review.hbm.xml

<class xmlns="urn:nhibernate-mapping-2.2" name="Review" table="Reviews">
    <id name="ReviewId" unsaved-value="0">
        <column name="ReviewId"></column>
        <generator class="native" />
    </id>

    <property name="Title" not-null="true" />
    <property name="Descrip" not-null="true" />
    <one-to-one name="TaggedReview" class="TaggedReview" /> <!-- This is probably very wrong?! -->
</class>

TaggedReview.hbm.xml

<class xmlns="urn:nhibernate-mapping-2.2" name="TaggedReview" table="TaggedReviews">
    <id name="ReviewId">
        <column name="ReviewId"></column>
        <generator class="native"/>
    </id>
    <one-to-one name="Review" class="Review" /> <!-- This is probably very wrong?! -->
    <property name="TaggedReviewDescrip" not-null="true" />
</class>

The property 'ReviewId' is the PK for the 'Reviews' table. It's a FK in the 'TaggedReviews' table.

There is ALWAYS 1 record/row in the TaggedReviews table for every record/row in the Reviews table - no more, no less.

I was also unsure about the 'TaggedReview' class as that table has NO PK, just a FK for the Reviews table (ReviewId), but it looked like the mapping file needed an id element in there, so wasn't sure about this either!

Can anyone please advise how to best configure this mapping?

like image 357
marcusstarnes Avatar asked Mar 03 '11 11:03

marcusstarnes


1 Answers

Ayende has a good explanation for one-to-one mappings here.

In your case the mappings should probably look like this:

Review.hbm.xml

<class xmlns="urn:nhibernate-mapping-2.2" name="Review" table="Reviews">
    <id name="ReviewId" unsaved-value="0">
        <column name="ReviewId"></column>
        <generator class="native" />
    </id>

    <property name="Title" not-null="true" />
    <property name="Descrip" not-null="true" />
    <one-to-one name="TaggedReview"
                      constrained="true"
                      foreign-key="none" 
                      class="TaggedReview" /> 
<!-- foreign-key="none", to prevent circular reference at insert -->
</class>

TaggedReview.hbm.xml

You will most likely need a primary key in the table, because you can't use the same column for the key and the foreign key.

<class xmlns="urn:nhibernate-mapping-2.2" name="TaggedReview" table="TaggedReviews">
    <id name="SomeOtherId">
        <column name="SomeOtherId"></column>
        <generator class="native"/>
    </id>
    <many-to-one name="Review" 
                 unique="true"
                 class="Review"> <!-- Use many-to-one for a foreign key -->
      <column name="ReviewId" />
    </many-to-one>
    <property name="TaggedReviewDescrip" not-null="true" />
</class>

If you cannot or do not want to change the db, you can take a look at NHibernate mapping - one-to-one (or one-to-zero).

like image 93
Florian Lim Avatar answered Sep 21 '22 12:09

Florian Lim