Связи NHibernate «многие ко многим», делающие оба конца родительскими, с помощью сущности отношения в модели предметной области
Объекты: Team <-> TeamEmployee <-> Сотрудник
Требования:
Команда и Сотрудник могут существовать без своего коллеги.В отношении Team-TeamEmployee команда несет ответственность (родитель) [используя позже TeamRepository].В отношении Employee-TeamEmployee Сотрудник несет ответственность (родитель) [используя позже EmployeeRepository].Дубликаты не допускаются.Удаление команды удаляет всех сотрудников в команде, если сотрудник не входит в другую команду.При удалении сотрудника удаляется только команда, если в команде больше нет сотрудников.Отображение:
public class TeamMap : ClassMap<Team>
{
public TeamMap()
{
// identity mapping
Id(p => p.Id)
.Column("TeamID")
.GeneratedBy.Identity();
// column mapping
Map(p => p.Name);
// associations
HasMany(p => p.TeamEmployees)
.KeyColumn("TeamID")
.Inverse()
.Cascade.SaveUpdate()
.AsSet()
.LazyLoad();
}
}
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
// identifier mapping
Id(p => p.Id)
.Column("EmployeeID")
.GeneratedBy.Identity();
// column mapping
Map(p => p.EMail);
Map(p => p.LastName);
Map(p => p.FirstName);
// associations
HasMany(p => p.TeamEmployees)
.Inverse()
.Cascade.SaveUpdate()
.KeyColumn("EmployeeID")
.AsSet()
.LazyLoad();
HasMany(p => p.LoanedItems)
.Cascade.SaveUpdate()
.LazyLoad()
.KeyColumn("EmployeeID");
}
}
public class TeamEmployeeMap : ClassMap<TeamEmployee>
{
public TeamEmployeeMap()
{
Id(p => p.Id);
References(p => p.Employee)
.Column("EmployeeID")
.LazyLoad();
References(p => p.Team)
.Column("TeamID")
.LazyLoad();
}
}
Создание сотрудников и команд:
var employee1 = new Employee { EMail = "Mail", FirstName = "Firstname", LastName = "Lastname" };
var team1 = new Team { Name = "Team1" };
var team2 = new Team { Name = "Team2" };
employee1.AddTeam(team1);
employee1.AddTeam(team2);
var employee2 = new Employee { EMail = "Mail2", FirstName = "Firstname2", LastName = "Lastname2" };
var team3 = new Team { Name = "Team3" };
employee2.AddTeam(team3);
employee2.AddTeam(team1);
team1.AddEmployee(employee1);
team1.AddEmployee(employee2);
team2.AddEmployee(employee1);
team3.AddEmployee(employee2);
session.SaveOrUpdate(team1);
session.SaveOrUpdate(team2);
session.SaveOrUpdate(team3);
session.SaveOrUpdate(employee1);
session.SaveOrUpdate(employee2);
После этого я фиксирую изменения с помощью транзакции.Commit (). Первая странная вещь заключается в том, что я должен спасти Команды и Сотрудников, а не одну из них (почему ?!). Если я сохраню только все команды или (Xor) всех сотрудников, тогда я получуTransientObjectException:
"объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом. Тип: Core.Domain.Model.Employee, Entity: Core.Domain.Model.Employee"
Когда я сохраняю все созданные Команды и Сотрудники, все сохраняется нормально, НО таблица отношений TeamEmployee имеетдубликаты.
ID EID TID
1 1 1
2 2 1
3 1 2
4 2 3
5 1 1
6 1 2
7 2 3
8 2 1
Таким образом, вместо 4 отношений есть 8 отношений. 4 отношения для левой стороны и 4 отношения для правой стороны. : [
Что я не прав?
Дополнительные вопросы: Когда я удаляю команду или сотрудника, нужно ли мне удалять команду или сотрудника из списка TeamEmployee в объектной модели, или NHibernate выполняет работу за меня (используя session.delete (..))?