通过使用域模型中的关系实体,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。

签出,特别是如何设置
产品
商店
之间的映射。

签出,特别是如何设置
产品
商店
之间的映射。

NHibernate不允许在两端与父级的多对多关联。

您谈论的是业务逻辑。NHibernate的目的不是实现业务逻辑

代码正在执行的操作:

您映射了两个不同的
TeamEmployee
集合,一个在
Team
中,一个在
Employee