Search code examples
nhibernatefluent-nhibernate-mapping

How to map an value object in his own table with Fluent NHibernate?


I have the following scenario: I have a component of an entity, but instead of store it in the same table I need to store in a separate table. The relationship between this two tables is one to one at most (1-0:1). The id of the component table is given by the main table, as value object it doesn't have an identity. Now I wonder how can I map the component to be stored in his own table without add an Id to it in the domain model.


Solution

  • There are three main ways to map a one-to-one relationship: inheritance, one-to-one, and join. I'm pretty sure that all three of these can be configured to share primary keys instead of having to add an additional primary key column. In this case, join sounds like the best fit, since you wouldn't have to create a separate entity. Ayende's article is the best resource for understanding join.

    Example (from Ayende's article, but adding a component to the mix):

    <class name="Person"
           table="People">
    
      <id name="Id">
        <generator class="identity"/>
      </id>
      <property name="Name" />
    
      <join table="Addresses">
        <key column="PersonId"/>
        <component name="Address"
                   class="Address">
          <property name="Line1"/>
          <property name="Line2"/>
          <property name="City"/>
          <property name="Country"/>
          <property name="ZipCode"/>
        </component>
      </join>
    </class>
    

    The classes for this would look like:

    public class Person
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual Address Address { get; set; }
    }
    
    public class Address
    {
        public string Line1 { get; set; }
        public string Line2 { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
        public string ZipCode { get; set; }
    }
    

    Note that Address does not have an Id property, and it's properties are not virtual. This is because Address is not an entity, it is a component. But join allows it to live in a separate table from Person's other properties.