通过使用域模型中的关系实体,NHibernate多对多关联,将两端作为父对象
实体: 团队员工 要求:通过使用域模型中的关系实体,NHibernate多对多关联,将两端作为父对象,nhibernate,fluent-nhibernate,many-to-many,one-to-many,domain-model,Nhibernate,Fluent Nhibernate,Many To Many,One To Many,Domain Model,实体: 团队员工 要求: 一个团队和一名员工可以在没有对应人员的情况下生存 在团队-员工关系中,团队是负责人(家长)[稍后使用团队存储库] 在员工团队员工关系中,员工是负责人(家长)[稍后使用EmployeeRepository] 不允许重复 如果员工不在另一个团队中,则删除团队将删除该团队中的所有员工 如果团队不包含更多员工,则删除员工只会删除该团队 映射: public class TeamMap : ClassMap<Team> { public TeamMap()
- 一个团队和一名员工可以在没有对应人员的情况下生存
- 在团队-员工关系中,团队是负责人(家长)[稍后使用团队存储库]
- 在员工团队员工关系中,员工是负责人(家长)[稍后使用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();
}
}
在此之后,我使用transaction.commit()提交更改。
第一件奇怪的事是,我必须拯救团队和员工,而不是他们中的一个(为什么?!)。如果我只保存所有团队或(Xor)所有员工,那么我会得到一个TransientObject异常:
“对象引用了一个未保存的
瞬态实例-保存
冲洗前的瞬态实例。
类型:Core.Domain.Model.Employee,
实体: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个关系:[
我错了什么
进一步的问题:当我删除一个团队或员工时,我是否必须从对象模型中的团队员工列表中删除该团队或员工,或者NHibernate是否为我做了该工作(使用session.delete(…)?看起来您需要一个HasManyToMany而不是两个HasMany映射。此外,不需要TeamEmployeeMap,除非您在该表中有其他需要映射的属性。另一件事,只有一侧需要反向()设置,因为您要向员工添加团队,所以我认为您需要将团队映射设置为反向。仅将反向设置为一侧将消除数据库中的重复条目 也许是这样的:
public class TeamMap : ClassMap<Team>
{
public TeamMap()
{
// identity mapping
Id(p => p.Id)
.Column("TeamID")
.GeneratedBy.Identity();
// column mapping
Map(p => p.Name);
// associations
HasManyToMany(x => x.TeamEmployees)
.Table("TeamEmployees")
.ParentKeyColumn("TeamID")
.ChildKeyColumn("EmployeeID")
.LazyLoad()
.Inverse()
.AsSet();
}
}
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
HasManyToMany(x => x.TeamEmployees)
.Table("TeamEmployees")
.ParentKeyColumn("EmployeeID")
.ChildKeyColumn("TeamID")
.Cascade.SaveUpdate()
.LazyLoad()
.AsSet();
HasMany(p => p.LoanedItems)
.Cascade.SaveUpdate()
.LazyLoad()
.KeyColumn("EmployeeID");
}
}
公共类团队地图:类地图
{
公共团队地图()
{
//身份映射
Id(p=>p.Id)
.列(“团队ID”)
.GeneratedBy.Identity();
//列映射
Map(p=>p.Name);
//联想
HasManyToMany(x=>x.TeamEmployees)
.表格(“团队员工”)
.ParentKeyColumn(“团队ID”)
.ChildKeyColumn(“雇员ID”)
.LazyLoad()
.Inverse()
.AsSet();
}
}
公共类EmployeeMap:ClassMap
{
公共雇员地图()
{
//标识符映射
Id(p=>p.Id)
.栏(“员工ID”)
.GeneratedBy.Identity();
//列映射
地图(p=>p.EMail);
Map(p=>p.LastName);
Map(p=>p.FirstName);
//联想
HasManyToMany(x=>x.TeamEmployees)
.表格(“团队员工”)
.ParentKeyColumn(“员工ID”)
.ChildKeyColumn(“团队ID”)
.Cascade.SaveUpdate()
.LazyLoad()
.AsSet();
有许多(p=>p.贷款项目)
.Cascade.SaveUpdate()
.LazyLoad()
.KeyColumn(“员工ID”);
}
}
使用此选项,删除操作将为您从数据库中删除TeamEmployee。看起来您需要一个HasManyToMany映射,而不是两个HasMany映射。此外,不需要TeamEmployeeMap,除非该表中有其他需要映射的属性。另一件事,只有一侧需要反向()设置,因为您要向员工添加团队,所以我认为您需要将团队映射设置为反向。仅将反向设置为一侧将消除数据库中的重复条目 也许是这样的:
public class TeamMap : ClassMap<Team>
{
public TeamMap()
{
// identity mapping
Id(p => p.Id)
.Column("TeamID")
.GeneratedBy.Identity();
// column mapping
Map(p => p.Name);
// associations
HasManyToMany(x => x.TeamEmployees)
.Table("TeamEmployees")
.ParentKeyColumn("TeamID")
.ChildKeyColumn("EmployeeID")
.LazyLoad()
.Inverse()
.AsSet();
}
}
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
HasManyToMany(x => x.TeamEmployees)
.Table("TeamEmployees")
.ParentKeyColumn("EmployeeID")
.ChildKeyColumn("TeamID")
.Cascade.SaveUpdate()
.LazyLoad()
.AsSet();
HasMany(p => p.LoanedItems)
.Cascade.SaveUpdate()
.LazyLoad()
.KeyColumn("EmployeeID");
}
}
公共类团队地图:类地图
{
公共团队地图()
{
//身份映射
Id(p=>p.Id)
.列(“团队ID”)
.GeneratedBy.Identity();
//列映射
Map(p=>p.Name);
//联想
HasManyToMany(x=>x.TeamEmployees)
.表格(“团队员工”)
.ParentKeyColumn(“团队ID”)
.ChildKeyColumn(“雇员ID”)
.LazyLoad()
.Inverse()
.AsSet();
}
}
公共类EmployeeMap:ClassMap
{
公共雇员地图()
{
//标识符映射
Id(p=>p.Id)
.栏(“员工ID”)
.GeneratedBy.Identity();
//列映射
地图(p=>p.EMail);
Map(p=>p.LastName);
Map(p=>p.FirstName);
//联想
HasManyToMany(x=>x.TeamEmployees)
.表格(“团队员工”)
.ParentKeyColumn(“员工ID”)
.ChildKeyColumn(“团队ID”)
.Cascade.SaveUpdate()
.LazyLoad()
.AsSet();
有许多(p=>p.贷款项目)
.Cascade.SaveUpdate()
.LazyLoad()
.KeyColumn(“员工ID”);
}
}
使用此选项,删除操作将为您从数据库中删除TeamEmployee。签出,特别是如何设置
产品
和商店
之间的映射。签出,特别是如何设置产品
和商店
之间的映射。TeamEmployee
集合,一个在Team
中,一个在Employee
中