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.
2 Answers
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.
3 Comments
join allows you to spread an entity across multiple tables. Let me add an example - basically the same as Ayende's example, but showing how you would add a component to the mix.If the table with the value object is only referenced by one table you can use the primary key of that table as primary key but don't make any methods to access the field in the value object.
If the table is referenced by more other tables then you have to create an own primary key.
You need a primary key to at least join the tables.