Fluent NHibernate
Standard Mapping Relationships

If you haven't setup a Fluent NHibernate project before, you should checkout the GettingStarted: Introduction guide.

As mentioned in ClassMap, all mappings are done from inside the constructor of a ClassMap<T> derived class; so baring that in mind, all examples are going to exclude the surrounding class.

There are three relationships you can use to map between your entities, reference (many-to-one), has many (one-to-many), and has many to many (many-to-many); I'll start by discussing the exclusive features for each, then show the features that are common to both.

References / many-to-one

The References method is used to create a many-to-one relationship between two entities; that's where the current entity has a single property that is an instance of the other entity.

Simple reference

Here's a typical example of a References usage.

// schema
table Account ( // our entity
  CustomerId int foreign key (Customer) references (Id)
)
table Customer (
  Id int identity(1,1) primary key
)

// model
public class Account
{
  public Customer Customer { get; set; }
}

// mapping
public AccountMap()
{
  References(x => x.Customer);
}

This creates a relationship between the two tables. In NHibernate hbm mapping, it's equivalent to <many-to-one name="Customer" />.

Specifying a foreign key

If you're generating your schema from your mappings (see Schema Generation), you may want to name your foreign key, you can do that using the WithForeginKey method.

References(x => x.Customer)
  .WithForeignKey();

This creates a foreign key based on the naming of your entities; if this example were an Account that has a Customer, the foreign key would be called FK_Account_Customer. If you would prefer to specify your own key, you can use the WithForeignKey(string) overload.

Specifying the column name

If your foreign key Id has a different column name than what you're using for a property, then you can use the ColumnName method.

// schema
table Account ( // our entity
  Customer_RefId int foregin key (Customer) references (Id)
)
table Customer (
  Id int identity(1,1) primary key
)

// model
public Customer Customer { get; set; }

// mapping
References(x => x.Customer)
  .ColumnName("Customer_RefId");

If you need to specify multiple columns to use as a key, useful if the entity you're referencing has a composite-id, then you can use the WithColumns method.

References(x => x.Customer)
  .WithColumns("CustomerName", "CustomerReference");

Changing the referenced column

If you need to link to the entity you're referencing by something other than it's primary key, then you can use the PropertyRef method.

References(x => x.Customer)
  .PropertyRef(x => x.CustomerReference);

Handling null references

If it's allowed in your domain for a foreign key to be null, you may want to stipulate what behavior NHibernate should use on encountering a null; you can do this with theNotFound property.

References(x => x.Customer)
  .NotFound.Ignore();

The default behavior is Exception.

HasMany / one-to-many

The HasMany method is used to create a one-to-many relationship between two entities; that's where the current entity has a collection of instances of the other entity.

Simple HasMany

Here's a typical example of a HasMany usage.

// schema
table Account ( // our entity
  Id int identity(1, 1) primary key
)
table Customer (
  AccountId int foreign key (Account) references (Id)
)

// model
public class Account
{
  public IList<Customer> Customers { get; private set; }

  public Account()
  {
    Customers = new List<Customer>();
  }
}

// mapping
public AccountMap()
{
  HasMany(x => x.Customers);
}

This creates a relationship between the two tables. In NHibernate hbm mapping, it's equivalent to:

<bag name="Customers">
  <key column="AccountId" />
  <one-to-many class="Account" />
</bag>

Specifying the foreign key name

If you need to specify multiple columns to use as a key, useful if the entity you're referencing has a composite-id, then you can use the WithKeyColumns method.

HasMany(x => x.Customers)
  . WithKeyColumns("CustomerName", "CustomerReference");

Similarly, if you just want to specify one column name you can use WithKeyColumn.

HasManyToMany / many-to-many

The HasManyToMany method is used to create a many-to-many relationship between two entities; that's where there's a reference between two tables, with an intermediary table.

Simple HasManyToMany

Here's a typical example of a HasManyToMany usage.

// schema
table Account ( // our entity
  Id int identity(1, 1) primary key
)
table AccountToCustomer (
  Account_id int foreign key (Account) references (Id)
  Customer_id int foreign key (Customer) references (Id)
)
table Customer (
  Id int identity(1, 1) primary key
)

// model
public class Account
{
  public IList<Customer> Customers { get; private set; }

  public Account()
  {
    Customers = new List<Customer>();
  }
}

// mapping
public AccountMap()
{
  HasManyToMany(x => x.Customers);
}

This creates a relationship between the two tables. In NHibernate hbm mapping, it's equivalent to:

<bag name="Customers">
  <key column="Customer_id" />
  <many-to-many class="Account" column="Account_id" />
</bag>

Setting the table name

If your design has a different intermediary table name, you can use the WithTableName method to set it.

HasManyToMany(x => x.Customers)
  .WithTableName("CustomerAddresses");

Specifying the foreign key names

If you need to override the foreign key names that are used in the intermediary table, you can use WithParentKeyColumn and WithChildKeyColumn.

table AccountToCustomer (
  Account_RefId int foreign key (Account) references (Id)
  Customer_RefId int foreign key (Customer) references (Id)
)

HasMany(x => x.Customers)
  .WithParentKeyColumn("Account_RefId")
  .WithChildKeyColumn("Customer_RefId");

You can use either of these methods, or both together.

Common settings for relationships

These settings are common to either all the relationships, or just the HasMany and HasManyToMany; I'll specify which relationships they're for.

Specifying access strategies

For all relationships

If your entity uses a backing field for a property, or some other non-standard design, then you can map it using the Access property.

// model
public class Account
{
  private IList<Customer> customers = new List<Customer>();

  public IList<Customer> Customers
  {
    get { return customers; }
  }
}

// mapping
HasMany(x => x.Customers)
  .Access.AsCamelCaseField();

The Access property can be used to set various combinations of Field and Property, with various casings and prefixes.

For example, for the same mapping but with the field called _customers you could use the Prefix.Underscore overload: Access.AsCamelCaseField(Prefix.Underscore).

Setting the fetch method

For all relationships

If you need to specify how joined entities are fetched, then you can use the Fetch property.

HasMany(x => x.Customers)
  .Fetch.Join();

The options are Join and Select.

Inverse

For all relationships

HasMany(x => x.Customers)
  .Inverse();

This sets the inverse attribute.

Cascade

For all relationships

HasMany(x => x.Customers)
  .Cascade.All();

This sets the cascade attribute; the options are All, None, SaveUpdate, Delete, and AllDeleteOrphan (for HasMany and HasManyToMany only).

Setting the collection type

For HasMany and HasManyToMany only

You can override the type of collection that is used for relationships, you can read more about this in Standard Mapping Collection Types.

The default is to use bag, but you can override it with the explicit methods.

HasMany(x => x.Customers)
  .AsSet();