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.
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.
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" />.
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.
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");
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);
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.
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.
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>
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.
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.
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>
If your design has a different intermediary table name, you can use the WithTableName method to set it.
HasManyToMany(x => x.Customers)
.WithTableName("CustomerAddresses");
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.
These settings are common to either all the relationships, or just the HasMany and HasManyToMany; I'll specify which relationships they're for.
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).
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.
For all relationships
HasMany(x => x.Customers) .Inverse();
This sets the inverse attribute.
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).
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();