如何从双向多对多关联中删除子项?

时间:2010-01-02 20:12:55

标签: nhibernate many-to-many associations

如何从双向多对多关联中删除儿童?

删除子项不起作用,因为我收到异常(FK违规)。

只是从父项中删除子项并在父项上调用saveorupdate不会执行任何操作。

实体:

public class Employee : Entity
{
    public virtual string LastName { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string EMail { get; set; }
    public virtual IList<LoanedItem> LoanedItems { get; set; }
    public virtual ISet<Team> Teams { get; set; }

    public Employee()
    {
        if (LoanedItems == null)
        {
            LoanedItems = new List<LoanedItem>();
        }

        if (Teams == null)
        {
            Teams = new HashedSet<Team>();
        }
    }

    public virtual void AddTeam(Team team)
    {
        Teams.Add(team);
        team.Employees.Add(this);
    }

    public virtual void RemoveTeamFromEmployee(Team team)
    {
        Teams.Remove(team);
    }
}

public class Team : Entity
{
    public virtual string Name { get; set; }
    public virtual ISet<Employee> Employees { get; set; }

    public Team()
    {
        if (Employees == null)
        {
            Employees = new HashedSet<Employee>();
        }
    }

    public virtual void RemoveEmployeeFromTeam (Employee employee)
    {
        var result = Employees.Remove(employee);
    }

    public virtual void AddEmployee(Employee employee)
    {
        Employees.Add(employee);
        employee.Teams.Add(this);
    }
}

映射:

public class TeamMap : ClassMap<Team>
{
    public TeamMap()
    {
        // identity mapping
        Id(p => p.Id)
            .Column("TeamId")
            .GeneratedBy.Identity();

        // column mapping
        Map(p => p.Name);

        // Employee is responible for the relationship
        HasManyToMany(p => p.Employees)
            .Table("TeamEmployee")
            .AsSet()
            .LazyLoad()
            .Inverse()
            .Cascade.SaveUpdate()
            .ParentKeyColumn("TeamId")
            .ChildKeyColumn("EmployeeId")
            .NotFound.Ignore();

    }
}

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);

        // Employee is responible for the relationship
        HasManyToMany(p => p.Teams)
            .Table("TeamEmployee")
            .AsSet()
            .LazyLoad()
            .ParentKeyColumn("EmployeeId")
            .ChildKeyColumn("TeamId")
            .Cascade.SaveUpdate()
            .NotFound.Ignore();

        HasMany(p => p.LoanedItems)
            .Cascade.SaveUpdate()
            .KeyColumn("EmployeeId");
    }
}

修改

删除团队的代码:

//Test Case 2
//Delete Team 2
Team team = session.Get<Team>(2);

List<Employee> employees = team.Employees.ToList();

foreach (var employee in employees)
{
    team.RemoveEmployeeFromTeam(employee);
}

session.Delete(team);

1 个答案:

答案 0 :(得分:2)

如果是多对多,则一个方向是“主”方向。另一个方向将定义inverse="false"。你必须以正确的方式从集合中删除 - 以确保(并真实地表示你的删除实现了什么),删除两者。然后刷新会话以保持此状态。

示例:

如果A包含B类型的对象集合,而反之亦然,那么要删除两个特定实例之间的关联,您必须删除实例来自A集合的实例B,反之亦然。然后当刷新会话时,NHibernate知道从链接表中删除相关的行。

现在编辑您已发布代码

尝试更改两种方法,如下所示:

public virtual void RemoveTeamFromEmployee(Team team)
{
    Teams.Remove(team);
    team.Employees.Remove(this);
}

public virtual void RemoveEmployeeFromTeam (Employee employee)
{
    Employees.Remove(employee);
    employee.Teams.Remove(this);
}

要整理代码以删除不对关系负责的团队,您必须迭代链接的员工。但是,如果您必须比员工更频繁地删除团队,那么您可能会发现更方便地撤消这一点,然后您可以使用:

team.Employees.Clear();
session.Delete(team);