NHibernar asociaciones de muchos a muchos que hacen ambos extremos como padre utilizando una entidad de relación en el Modelo de dominio
Entidades: Team <-> TeamEmployee <-> Employee
Requisitos:
Un Equipo y un Empleado pueden existir sin su contraparte.En la relación Team-TeamEmployee el equipo es responsable (padre) [usando más tarde un TeamRepository].En la relación Empleado-EquipoEmpleado, el Empleado es responsable (padre) [usando más tarde un EmployeeRepository].No se permiten duplicados.Eliminar un equipo elimina a todos los empleados en el equipo, si el empleado no está en otro equipo.Eliminar un Empleado solo elimina un Equipo, si el Equipo no contiene más Empleados.Cartografía:
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();
}
}
Creación de empleados y equipos:
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);
Después de esto confirmo los cambios usando transaction.Commit (). La primera cosa extraña es que tengo que salvar Equipos y Empleados en lugar de uno solo de ellos (¿por qué?). Si solo salvo a todos los equipos o (Xor) a todos los empleados, obtengo unTransientObjectException:
"el objeto hace referencia a una instancia transitoria no guardada: guarde la instancia transitoria antes de vaciar. Escriba: Core.Domain.Model.Employee, Entity: Core.Domain.Model.Employee"
Cuando guardo todos los Equipos y Empleados creados, todo se guarda bien, PERO la tabla de relación que TeamEmployee tieneduplicaciones.
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
Así que en lugar de 4 relaciones hay 8 relaciones. 4 relaciones para el lado izquierdo y 4 relaciones para el lado derecho. :
¿En qué me equivoco?
Otras preguntas: cuando elimino un Equipo o un Empleado, ¿tengo que eliminar al equipo o al Empleado de la lista de Empleados del Equipo en el modelo de objeto o NHibernate hace el trabajo por mí (usando session.delete (..))?