Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate mapping - one-to-one (or one-to-zero)

NHibernatians!

I have a table [dbo].[Wibble] and another table [dbo].[WibbleExtended].

[Wibble] is the main table and [WibbleExtended] is an optional table where some other fields are stored. There are far fewer entries in the [WibbleExtended] table than the main [Wibble] table. I think this was done back in the day to cure some space issues (Wibble has many rows and WibbleExtened has many columns).

The ID for each table is the same and comes from an external source.

I.e.

[dbo].[Wibble].[WibbleId]

and

[dbo].[WibbleExtended].[WibbleId]

are identical and is how the two tables relate.

N.B. I can't change the schema. I'm shoe-horning this onto a legacy system that I have almost no control over.

Searching around it seems that one-to-one mappings are problematic and the prevailing wisdom is to use two many-to-one mappings.

My mappings currently are:

<class name="Wibble" table="Wibble" >
   <id name="Id" column="WibbleId" type="Int32">
      <generator class="assigned"/>
   </id>

   <many-to-one name="WibbleExtended" class="WibbleExtended" column="WibbleId" not-null="false" cascade="all"/>
</class>

And

<class name="WibbleExtended" table="WibbleExtended" >
   <id name="Id" column="WibbleId" type="Int32">
        <generator class="assigned" />
   </id>

   <many-to-one name="Wibble" class="Wibble" column="WibbleId" not-null="true" />     
 </class>

The problem with this is I'm getting errors such as

System.IndexOutOfRangeException: Invalid index n for this SqlParameterCollection with Count=n.

I've looked around and this does look like the correct strategy, it's just falling at the final hurdle.

Is the problem the id generator? Other aspect of the mapping?

Free mince pie for the correct answer.

EDIT: Ok - here's what I did to solve this via @James Gregory.

  1. Moved the unit tests from the WibbleExtended tests to the Wibble test class and made the necessary modifications.

  2. Added the following to the Wibble.hbm.xml

    <join table="WibbleExtended" optional="true">
         <key column="WibbleId"/>
         <property name="Blah1" column="Blah1" type="String" length="2000" not-null="false" />
         <property name="Blah2" column="Blah2" type="String" length="1000" not-null="false" />    
    </join>
    
  3. Added the corresponding properties to the Wibble POCO.

  4. Deleted all code relating to WibbleExtended.

  5. Run tests, all passed, checked in. Build passed. Went for an xmas beer (hence it's been a couple of days before I updated this! :-))

like image 959
Iain Holder Avatar asked Dec 23 '08 13:12

Iain Holder


People also ask

What is the difference between NHibernate and fluent NHibernate?

Fluent NHibernate offers an alternative to NHibernate's standard XML mapping files. Rather than writing XML documents, you write mappings in strongly typed C# code. This allows for easy refactoring, improved readability and more concise code.

Is NHibernate better than Entity Framework?

EF Core can use a ROWVERSION/TIMESTAMP column on SQL Server, or any of a list of columns, when updating a record. NHibernate offers richer capabilities, besides SQL Server ROWVERSION/TIMESTAMP, it can also use database native mechanisms such as Oracle's ORA_ROWSCN, but also timestamp or version columns.

What is NHibernate in .NET core?

NHibernate is a mature, open source object-relational mapper for the . NET framework. It's actively developed, fully featured and used in thousands of successful projects.

What is fetch in NHibernate?

A fetching strategy is the strategy NHibernate will use for retrieving associated objects if the application needs to navigate the association. Fetch strategies may be declared in the O/R mapping metadata, or overridden by a particular HQL or Criteria query.


2 Answers

The error you are getting:

Invalid index n for this SqlParameterCollection with Count=n.

is due to two properties mapped to the same column. Use insert=false and update=false in one of the two.

reference http://groups.google.com/group/nhusers/browse_thread/thread/84830b1257efd219

like image 104
Jalal El-Shaer Avatar answered Oct 30 '22 06:10

Jalal El-Shaer


Have you considered using the Join element that was introduced in NHibernate 2.0? This element allows you to join multiple tables to form one entity; that relationship can also be optional.

like image 40
James Gregory Avatar answered Oct 30 '22 07:10

James Gregory