Is there a way to specify a many-to-one and one-to-many relationship using a joining table?
The relations are:
Owners - may or may not have cars.
Cars - may have zero or one owners.
I wanted to model this using a joining table (CarsForOwner) rather than having a nullable ownerId field in cars but I'm having trouble working out the nHibernate mappings for this.
The best I've been able to come is to have a many-to-many mapping in Car and hide the set from the rest of the code. Use a property for Owner that ensures 0 to 1 owners are in the set.
The problem with this solution is it prevents navigating the Owner property in HQL or criterias as a simple property.
NHibernate Version
1.2.1.4000
Mapping file
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
default-access="field.camelcase"
default-lazy="false"
assembly="ManyToOne"
namespace="ManyToOne"
schema="dbo"
>
<class name="Owner" table="Owners">
<id name="Id" column="ownerId">
<generator class="native"/>
</id>
<property name="Name"/>
</class>
<class name="Car" table="Cars">
<id name="Id" column="carId">
<generator class="native"/>
</id>
<property name="Model"/>
</class>
</hibernate-mapping>
Test sqlCode:
CREATE TABLE Owners
(
ownerId int identity(1,1) not null PRIMARY KEY,
name nvarchar(255) not null
)
CREATE TABLE Cars
(
carId int identity(1,1) not null PRIMARY KEY,
model nvarchar(255) not null
)
CREATE TABLE CarsForOwner
(
carId int not null PRIMARY KEY,
ownerId int not null,
CONSTRAINT FK_CarsForOwner_Owners
FOREIGN KEY (ownerId)
REFERENCES Owners (ownerId),
CONSTRAINT FK_CarsForOwner_Cars
FOREIGN KEY (carId)
REFERENCES Cars (carId)
)
GO
INSERT INTO Owners ([name]) VALUES ('Fred')
INSERT INTO Owners ([name]) VALUES ('Bob')
INSERT INTO Cars (model) VALUES ('Toyota Yaris')
INSERT INTO Cars (model) VALUES ('Ford Mondao')
INSERT INTO Cars (model) VALUES ('MR2')
INSERT INTO Cars (model) VALUES ('Ownerless')
INSERT INTO CarsForOwner (carId, ownerId) VALUES (1, 1)
INSERT INTO CarsForOwner (carId, ownerId) VALUES (2, 1)
INSERT INTO CarsForOwner (carId, ownerId) VALUES (3, 2)
GO
Test codeCode:
class Program
{
static void Main()
{
Configuration cfg = new Configuration();
cfg.Configure();
ISessionFactory factory = cfg.BuildSessionFactory();
ISession session = factory.OpenSession();
IList<Car> cars = session.CreateCriteria(typeof(Car)).List<Car>();
foreach (Car c in cars) Console.WriteLine(c);
Console.ReadKey();
}
}
public class Owner
{
private int? id;
private string name;
public int? Id
{
get { return id; }
set { id = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public override string ToString()
{
return string.Format("{{ Id = {0}, Name = {1} }}", id, name);
}
}
public class Car
{
private int? id;
private Owner owner;
private string model;
public int? Id
{
get { return id; }
set { id = value; }
}
public Owner Owner
{
get { return owner; }
set { owner = value; }
}
public string Model
{
get { return model; }
set { model = value; }
}
public override string ToString()
{
return string.Format("{{ Id = {0}, Model = {1}, Owner = {2} }}", id, model, owner);
}
}
Edit: just changed the subject to read many-to-one, as this is the relationship direction I'm most interested in, the one-to-many is simple.