tags:

views:

156

answers:

3

Hi all,

I have a problem with nhibernate when I try to insert an object with an one-to-one relationship to another object. There is a class called Article

Mapping file

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

<id name="ID" column="article_id" type="Int32" unsaved-value="0">
    <generator class="native"/>
</id>

<property name="Title" column="title" type="String" not-null="true" length="255" />
<property name="Body" column="body" type="String" length="1073741823" />
<property name="IsEnabled" column="is_enabled" type="Boolean" not-null="true" />

<many-to-one name="ParentArticle" class="..." column="parent_id" cascade="all" />

<bag name="Children" lazy="true" cascade="all-delete-orphan" >
  <key column="parent_id" />
  <one-to-many class="..." />
</bag>

The class itself follows from this mapping file and is omitted for the sake of simplicity.

Then there is another class called SpecialArticle. The mapping for this class is as follows:

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

<id name="ID" column="id" type="Int32" unsaved-value="0">
    <generator class="native"/>
</id>

<property name="Price" column="Price" type="Double" not-null="true" />
<one-to-one name="Article" class="..." fetch="join" cascade="all" />

The ArticleExtension class then is:

    public class SpecialArticle
{
    /// <summary>
    /// Get/Set the ID for this question
    /// </summary>
    public virtual int ID
    {
        get;
        set;
    }

    /// <summary>
    /// Get/Set the expected price for this question or answer
    /// </summary>
    public virtual Double Price
    {
        get;
        set;
    }

    /// <summary>
    /// Get/Set the article that contains the rest of the information for this question
    /// </summary>
    public virtual Article Article
    {
        get;
        set;
    }
}

when i want to insert a special article in the db i do:

// Populate someArticle
// Populate someSpecialArticle
// Following code is wrapped in a transaction
someSpecialArticle.Article = someArticle;
Session.SaveOrUpdate(someArticle);
Session.SaveOrUpdate(someSpecialArticle);

Object someArticle is inserted ok, but the insert statement for object someSpecialArticle is: INSERT INTO tbl (Price) VALUES (@p0); select SCOPE_IDENTITY()

where is the article_id to specify the parent article???

thx

A: 

Proper mapping is:

<many-to-one name="Article" fetch="join" cascade="all" unique="true" />

When you create one to one mapping in NHibernate one side must be mapped as many-to-one - that will be the side responsible for storing foreign key. Since you have one way relationship here you must map it as many-to-one and use unique constraint to make relationship behave like one-to-one

maciejkow
A: 

It would be easier to use a many-to-one relationship from SpecialArticle to Article. The one-to-one relationship can be tricky and isn't a recommended approach.

In your case, it sounds like making SpecialArticle extend Article might be an appropriate solution. Then you could use a join-subclass to get the additional information needed for a SpecialArticle in the second table.

g .
A: 

the problem is that i cant change the article mapping or class to define a join-subclass. is there any alternative?

Yannis
This should be a comment; it isn't an answer.Try using a many-to-one mapping.
g .
but then the specialarticle object will contain a list of articles right?
Yannis
no, it'll still contain one article. One-to-many is a collection
maciejkow
yes i know. but it will be represented as a collection right. Like IList<Article>.
Yannis
what i mean is that although i am expecting one parent article back i have to rrepresent it as a collection. Then in order to consume it it will be very cumbersome (will have to check the contents, count, and do [0] to get it out). right?
Yannis
I sorted it out by using your suggestion. Thanks everyone that took the time to help me out.
Yannis