Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,026 | Comments: 44,842

filter by tags archive

NHibernate Mapping - <one-to-one/>

time to read 7 min | 1254 words

In the database world, we have three kind of associations: 1:m, m:1, m:n.

However, occasionally we want to have a one to one relationship. We could simulate it easily enough on the database side using two many to one relations, but that would require us to add the association column to both tables, and things gets… tricky when it comes the time to insert or update to the database, because of the cycle that this creates.

NHibernate solves the problem by introducing a one-to-one mapping association, which allow you to define the two relationships based on a single column in the database, which controls the two way association.

        name="PropertyName"                                (1)
        class="ClassName"                                  (2)
        cascade="all|none|save-update|delete"              (3)
        constrained="true|false"                           (4)
        fetch="join|select"                                (5)
        property-ref="PropertyNameFromAssociatedClass"     (6)
        access="field|property|nosetter|ClassName"         (7)

1, 2, 3, 6, 7 were all discussed elsewhere, so I’ll skip them and move directly to showing how this can be used.

We have the follow object model:


And the database model:


Note that while in the object model we have a bidirectional mapping, in the database we have only a single reference on the employees table. In the relational model, all associations are naturally bidirectional, but that is not true on the object model. In order to bridge this inconsistency, we map them as:

<class name="Employee"

	<id name="Id">
		<generator class="native"/>
	<property name="Role"/>

	<many-to-one name="Person"

<class name="Person"

	<id name="Id">
		<generator class="native"/>
	<property name="Name" />
	<one-to-one name="Employee"

We have a unique many-to-one association from Employee to Person, but a one to one from Person to Employee. This will reuse the many-to-one association defined in the Employee mapping.

Let see how this works for saving and loading the data:

using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
	var person = new Person
		Name = "test",
	var employee = new Employee
		Person = person,
		Role = "Manager"
	person.Employee = employee;
session.Save(employee); tx.Commit(); } // person to employee using (var session = sessionFactory.OpenSession()) using (var tx = session.BeginTransaction()) { var employee = session.Get<Person>(1).Employee; Console.WriteLine(employee.Role); tx.Commit(); } // employee to person using (var session = sessionFactory.OpenSession()) using (var tx = session.BeginTransaction()) { var person = session.Get<Employee>(1).Person; Console.WriteLine(person.Name); tx.Commit(); }

And the SQL that would be generated would be:


This is quite interesting. We can see that we insert the entities as we expect, but when we pull a person out, we do a join to the employee, to get the one-to-one association. For that matter, even in the second scenario, we do a join to get the associated employee.

The reason that we have to do it is quite interesting as well. NHibernate makes some guarantees about the way the object model and the database model map to one another. And one of those guarantees is that if there is no association in the database, we will get back a null in the object model.

Generally, this works very well, since we can tell whatever an association exists or not using the value in the table (for many-to-one associations). But for one-to-one association, if we want to keep this guarantee, we have to check the associated table to verify if we need to have a null or a proxy there. That is somewhat annoying, but we can get around that by specifying constrained=”true”. This tell NHibernate that in this case, whenever there is a Person, there must also be a matching Employee value. We can specify it like this:

<one-to-one name="Employee" 

Something else to note is that we must specify this with foreign-key=”none”, because otherwise NHibernate’s Schema Export feature would create two foreign keys for us, which would create a circular reference that wouldn’t allow us to insert anything into the database.

When setting this, we can see that there is a dramatic change in NHibernate’s behavior:


Instead of generating joins, NHibernate now uses standard selects to get the data. And we don’t have to pre-populate the information on loading the entity, we can delay that as we usually do with NHibernate.

And the last thing that we will explore for <one-to-one/> is the fetch attribute. It defaults to select, so we have already seen how that works, but when we set fetch=”join”, we get an interesting flashback. Well, almost:


Again, we use a join to get the value upfront, but since we are now using constrained=”true”, we can use an inner join instead of a left outer join, which is more efficient in most cases.




Is it possible set new Employee on existing Person?

Thanks for reply.

Steve Willcock

Great explanation, the constrained="true" / foreign-key="none" part is really helpful.


How do you emulate a one to many relationship in ActiveRecord, where you need to filter the key based on a column? For example my MailAccount has lots of Contacts, but I only want to those Contacts of a particular type in the relationship? From what I can see it's not possible in AR, but is in NH.

Ayende Rahien


Yes, it is possible. Take care to ensure that it is always set to A person, if you are using constrained, though.


Use the Where property


Your sample doesnt work if I use guid generator. I think this sample is not correct way using one-to-one mapping.

Ayende Rahien


what is the error you are getting?


In database person with id=8, employee with id=3(and in person column 8).


using (var session = sessionFactory.OpenSession())

        using (var tx = session.BeginTransaction())


            var employee = session.Get






SELECT person0.Id as Id10_,

   person0_.Name as Name1_0_

FROM People person0_

WHERE person0_.Id = 8 /* @p0 */

SELECT employee0.Id as Id01_,

   employee0_.Role   as Role0_1_,

   employee0_.Person as Person0_1_,

   person1_.Id       as Id1_0_,

   person1_.Name     as Name1_0_

FROM Employee employee0_

   left outer join People person1_

     on employee0_.Person = person1_.Id

WHERE employee0_.Id = 8 /* @p0 */

Exception was thrown:

No row with the given identifier exists[OneToOneEntities.Employee#8]

If I'll set fetch="join" on one-to-one association, NH will generate this query:

SELECT person0.Id as Id12_,

   person0_.Name     as Name1_2_,

   employee1_.Id     as Id0_0_,

   employee1_.Role   as Role0_0_,

   employee1_.Person as Person0_0_,

   person2_.Id       as Id1_1_,

   person2_.Name     as Name1_1_

FROM People person0_

   inner join Employee employee1_

     on person0_.Id = employee1_.Id -- Yeah!!!!!!!!!!!!!!!!

   left outer join People person2_

     on employee1_.Person = person2_.Id

WHERE person0_.Id = 8 /* @p0 */

and {"Object reference not set to an instance of an object."} Exception will be thrown.

one-to-one association bind primary keys:

<param Employee



£class name="Person" table="People"£

£id name="Id"£

    £generator class="foreign"£

      £param name="property"£ Employee £/param£



£property name="Name" /£

£one-to-one name="Employee" class="Employee" constrained="true"/£


Ayende Rahien


You set it up in such a way that the Id or Person and the Employee must have the same value.

That is what foreign means.


In your sample Person.Id, Employee.Id and Employee.Person, it's not real case, this what i want to say.


In your sample Person.Id, Employee.Id and Employee.Person equals, it's not real case, this what i want to say.

Luiz Sergio

How can I to create a mapping when a Person can be Employee and/or Customer and/or Author?

Ayende Rahien

Take a look at the "any" post


I have problem about this on Eager Load. my mapping file:



            class="MyDomain.Test.Employee, MyDomain" 

            cascade="all" fetch="join" lazy="false"/>



             class="MyDomain.Test.Person, MyDomain" unique="true" 


I have one person and one employee in my DB and I run this simple test:

        var person  = repository.FindByID(new Guid  (  "30ad691d-84c0-4175-815f-9bf800f86766"));


        Assert.That(person.Employee, Is.Not.Null);

It generate 2 sql statements:

NHibernate: SELECT person0.ID as ID41, person0.Name as Name41, employee1.ID as ID30, employee1.Name as Name30, employee1.PeopleID as PeopleID30 FROM People person0 left outer join Employees employee1_ on person0.ID=employee1.PeopleID WHERE person0_.ID=@p0; @p0 = '30ad691d-84c0-4175-815f-9bf800f86766'

NHibernate: SELECT employee0.ID as ID30, employee0.Name as Name30, employee0.PeopleID as PeopleID30_ FROM Employees employee0_ WHERE employee0_.PeopleID=@p0; @p0 = '30ad691d-84c0-4175-815f-9bf800f86766'

Which I assume it should only generate one.

Can I make it only generate one?

Ayende Rahien


Take a look at constrained="true"

Comment preview

Comments have been closed on this topic.


No future posts left, oh my!


  1. Technical observations from my wife (3):
    13 Nov 2015 - Production issues
  2. Production postmortem (13):
    13 Nov 2015 - The case of the “it is slow on that machine (only)”
  3. Speaking (5):
    09 Nov 2015 - Community talk in Kiev, Ukraine–What does it take to be a good developer
  4. Find the bug (5):
    11 Sep 2015 - The concurrent memory buster
  5. Buffer allocation strategies (3):
    09 Sep 2015 - Bad usage patterns
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats