Powerslave
Powerslave

Reputation: 457

NHibernate: Error when saving Bag with NOT-Nullable Constraint

Given are tables Item and ItemTranslation where the latter has a NOT-Nullable foreign key on Item.

ItemTranslation.hbm.xml only has its properties Text and LanguageCode, it does NOT map Item.

Item.hbm.xml:

<bag name="Translations" cascade="all-delete-orphan">
  <key column="ItemID" />
  <one-to-many class="ItemTranslation, SomeNamespace" />
</bag>

Now when I do the following:

Item item = new Item();
item.Translations.Add( new ItemTranslation { LanguageCode = "DE", Text = "Test DE" } );
item.Translations.Add( new ItemTranslation { LanguageCode = "EN", Text = "Test EN" } );
item.Save();

NHibernate throws the following exception:

System.Data.SqlClient.SqlException : Cannot insert the value NULL into column 'ItemID', table 'someDb.dbo.ItemTranslation'; column does not allow nulls. INSERT fails.
Cannot insert the value NULL into column 'ItemID', table 'someDb.dbo.ItemTranslation'; column does not allow nulls.

I could fix it either by mapping ItemID as many-to-one in IssuedItemTranslation.hbm.xml or making the column NULLable.

But both ways are kind of ugly.

Is there any other possibility? Maybe with some change in the bag-mapping?

Thank you in advance.

Upvotes: 0

Views: 241

Answers (2)

Radim K&#246;hler
Radim K&#246;hler

Reputation: 123891

If we do not want to use inverse mapping (see below) .. we must left the column in DB nullable.

That is how it works. NHibernate will

  • insert children (or parent)
  • insert parent (or children) read more here 9.6. Flush
  • update children with parent id

Another way: Inverse mapping

There is nothing bad on explicit Item back reference mapping on ItemTranslatin. I do that always. And If we really do not like it.. it could be protected property.

But then, we would need inverse mapping.

<bag name="Translations" cascade="all-delete-orphan" inverse="true">

And also set the reference on both sides.

Item item = new Item();
var tr1 = new ItemTranslation { 
  LanguageCode = "DE", 
  Text = "Test DE"
  Item = item } ;
item.Translations.Add(tr1);
...

This solution does not require item column to be nullable...

That would be the way I suggest. Read more here:

Upvotes: 1

Powerslave
Powerslave

Reputation: 457

It works when mapping the bag as follows:

<bag name="Translations" cascade="all-delete-orphan">
  <key column="ItemID" not-null="true" update="false" />
  <one-to-many class="ItemTranslation, SomeNamespace" />
</bag>

Is this the correct solution?

Upvotes: 0

Related Questions