【问题标题】:How to delete a child from a bidirectional many-to-many association?如何从双向多对多关联中删除孩子?
【发布时间】:2010-12-31 20:24:51
【问题描述】:

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

删除孩子不起作用,因为我遇到异常(FK Violation)。

只是从父级中删除子级并在父级上调用 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);

【问题讨论】:

    标签: nhibernate many-to-many associations


    【解决方案1】:

    如果是多对多,那么一个方向就是“主”方向。另一个方向将定义inverse="false"。您必须以正确的方式从集合中删除 - 确保(并真正代表您的删除所达到的效果),删除两者。然后刷新会话以使其保持不变。

    例子:

    如果A 具有B 类型的对象集合,反之亦然,那么要删除两个特定实例之间的关联,您必须从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);
    

    【讨论】:

    • 从收藏中删除的正确方法是什么?我在 NH 事务范围内使用了我的调用,所以我不需要手动刷新。
    • 您能否编辑您的问题以包括相关的类和映射定义?
    • 就是这样。我想从员工(父)中删除一个团队(子)。
    • 啊酷,是的,这行得通!但是我怎样才能更好地编写代码呢?看看编辑过的问题...
    • team.Employees.Clear();在我看来看起来很丑陋,但它应该可以工作,因为 NHibernate 只会真正删除团队。但是当我重用Employees集合时它是空的,我认为这是错误的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多