Fluent NHibernate Mappings: Cheat Sheet
Here is a "cheat sheet" for most of the different types of mappings I normally need to deal with in a Domain Model.
Domain Model - based on a Football Team (Australian Rules Football):
public class Team
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
//One to one (uni directional)
public virtual President President { get; set; }
//One to one (bi directional)
public virtual Coach Coach { get; set; }
//One to many (uni directional)
public virtual IList<Player> Players { get; set; }
//One to many (bi directional)
public virtual IList<AssistantCoach> AssistantCoaches { get; set; }
//Component
public virtual Stadium HomeGround { get; set; }
}
public class Stadium
{
public virtual string Name { get; set; }
public virtual string Location { get; set; }
}
public class Player
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual int Number { get; set; }
}
public class Coach
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual DateTime AppointmentDate { get; set; }
public virtual Team Team { get; set; }
}
public class AssistantCoach
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual CoachingLine Line { get; set; }
public virtual Team Team { get; set; }
}
public enum CoachingLine
{
ForwardLine,
Midfield,
BackLine
}
public class President
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
Entity Mappings
public class TeamMapping : ClassMap<Team>
{
public TeamMapping()
{
//Properties
Id(entity => entity.Id);
Map(entity => entity.Name);
//One to many (uni-directional)
HasMany(x => x.Players)
.KeyColumn("TeamId")
.Not.Inverse()
.Not.KeyNullable()
.Not.KeyUpdate()
.Cascade.All();
//One to many (bi-directional)
HasMany(x => x.AssistantCoaches)
.KeyColumn("TeamId")
.Inverse() //This ensures the TeamId is INSERTED (rather than an INSERT with null teamid, and then an UPDATE to set the teamid)
.Cascade.All();
//One to one (bi-directional) - foreign key from Child -> Parent
HasOne(x => x.Coach)
.Cascade.All();
//One to one (uni-directional) - foreign key from Parent -> Child
References(x => x.President)
.Column("PresidentId")
.Cascade.All();
//Component
Component(x => x.HomeGround, m =>
{
m.Map(x => x.Name, "HomeGroundName");
m.Map(x => x.Location, "HomeGroundLocation");
});
}
}
public class PlayerMapping : ClassMap<Player>
{
public PlayerMapping()
{
Id(entity => entity.Id);
Map(entity => entity.Name);
Map(entity => entity.Number);
}
}
public class CoachMapping : ClassMap<Coach>
{
public CoachMapping()
{
Id(entity => entity.Id);
Map(entity => entity.Name);
Map(entity => entity.AppointmentDate);
//One to one (bi directional)
References(x => x.Team)
.Column("TeamId");
}
}
public class AssistantCoachMapping : ClassMap<AssistantCoach>
{
public AssistantCoachMapping()
{
Id(entity => entity.Id);
Map(entity => entity.Name);
Map(entity => entity.Line);
//Many to one - the other side of the One to Many (bi-directional)
References(x => x.Team)
.Column("TeamId");
}
}
public class PresidentMapping : ClassMap<President>
{
public PresidentMapping()
{
Id(entity => entity.Id);
Map(entity => entity.Name);
}
}
Test (a very simple test)
[TestClass]
public class NHibernateTests
{
private const string ConnectionString = @"data source=(local);Integrated Security=SSPI;Database=NHibernateSample";
[TestInitialize]
public void Setup()
{
var factory = new NHibernateUnitOfWorkFactory<Team>(ConnectionString);
factory.CreateDatabase();
UnitOfWork.Initialise(factory);
}
[TestMethod]
public void Test()
{
var id = 0;
using(UnitOfWork.Create())
{
var team = new Team() {Name = "Melbourne Demons", Players = new List<Player>(), AssistantCoaches = new List<AssistantCoach>()};
team.Players.Add(new Player() {Name = "Jack Watts", Number = 4});
team.Players.Add(new Player() { Name = "Jack Trengove", Number = 9 });
team.Coach = new Coach() { Name = "Mark Neeld", AppointmentDate = new DateTime(2011, 10, 1), Team = team};
team.AssistantCoaches.Add(new AssistantCoach() { Name = "Jade Rawlings", Line = CoachingLine.BackLine, Team = team});
team.AssistantCoaches.Add(new AssistantCoach() { Name = "Brian Royal", Line = CoachingLine.Midfield, Team = team });
team.AssistantCoaches.Add(new AssistantCoach() { Name = "Leigh Brown", Line = CoachingLine.ForwardLine, Team = team });
team.President = new President() {Name = "Jim Stynes"};
team.HomeGround = new Stadium() {Name = "MCG", Location = "Richmond"};
UnitOfWork.Current.DatabaseSession.Add(team);
UnitOfWork.Commit();
id = team.Id;
}
using(UnitOfWork.Create())
{
var loadedTeam = UnitOfWork.Current.DatabaseSession.Get<Team>(id);
//Aggregate root
Assert.IsNotNull(loadedTeam);
//One to many (uni directional)
Assert.AreEqual(2, loadedTeam.Players.Count);
//One to many (bi directional)
Assert.AreEqual(3, loadedTeam.AssistantCoaches.Count);
//One to one (uni directional)
Assert.IsNotNull(loadedTeam.President.Name);
//One to one (bi directional)
Assert.IsNotNull(loadedTeam.Coach.Name);
//Component
Assert.IsNotNull(loadedTeam.HomeGround.Name);
}
}
}
NOTE: The UnitOfWork and NHibernateUnitOfWorkFactory are some wrapper classes that I have developed to help abstract away the ORM details. They are available on my GitHub account.
Generated SQL:
NHibernate: INSERT INTO [President] (Name) VALUES (@p0);
NHibernate: INSERT INTO [Team] (Name, PresidentId, HomeGroundName, HomeGroundLocation) VALUES (@p0, @p1, @p2, @p3);
NHibernate: INSERT INTO [Player] (Name, Number, TeamId) VALUES (@p0, @p1, @p2);
NHibernate: INSERT INTO [Player] (Name, Number, TeamId) VALUES (@p0, @p1, @p2);
NHibernate: INSERT INTO [AssistantCoach] (Name, Line, TeamId) VALUES (@p0, @p1, @p2);
NHibernate: INSERT INTO [AssistantCoach] (Name, Line, TeamId) VALUES (@p0, @p1, @p2);
NHibernate: INSERT INTO [AssistantCoach] (Name, Line, TeamId) VALUES (@p0, @p1, @p2);
NHibernate: INSERT INTO [Coach] (Name, AppointmentDate, TeamId) VALUES (@p0, @p1, @p2);
NHibernate: SELECT team0.Id as Id41, team0.Name as Name41, team0.PresidentId as Presiden341, team0.HomeGroundName as HomeGrou441, team0.HomeGroundLocation as HomeGrou541, coach1.Id as Id10, coach1.Name as Name10, coach1.AppointmentDate as Appointm310, coach1.TeamId as TeamId10_ FROM [Team] team0_ left outer join [Coach] coach1_ on team0.Id=coach1.Id WHERE team0_.Id=@p0;@p0 = 1 [Type: Int32 (0)]
NHibernate: SELECT players0.TeamId as TeamId1, players0.Id as Id1, players0.Id as Id20, players0.Name as Name20, players0.Number as Number20_ FROM [Player] players0_ WHERE players0_.TeamId=@p0;@p0 = 1 [Type: Int32 (0)]
NHibernate: SELECT assistantc0.TeamId as TeamId1, assistantc0.Id as Id1, assistantc0.Id as Id00, assistantc0.Name as Name00, assistantc0.Line as Line00, assistantc0.TeamId as TeamId00 FROM [AssistantCoach] assistantc0_ WHERE assistantc0_.TeamId=@p0;@p0 = 1 [Type: Int32 (0)]
NHibernate: SELECT president0.Id as Id30, president0.Name as Name30 FROM [President] president0_ WHERE president0_.Id=@p0;@p0 = 1 [Type: Int32 (0)]
Comments
No comments yet. Be the first!