NHibernate删除多对多父母和孩子

时间:2019-01-13 18:04:28

标签: nhibernate fluent-nhibernate nhibernate-mapping fluent-nhibernate-mapping

我有3节课。 公司地址办公室。以下是实体的定义。

公司:

public class Company: Identity
{
    public Company()
    {
        Offices = Offices ?? new List<Office>();
    }
    public virtual string Name { get; set; }
    public virtual IList<Office> Offices { get; set; }

    public virtual void AddOffice(Office office)
    {
        office.Company = this;
        Offices.Add(office);
    }
}

地址:

public class Address: Identity
{
    public Address()
    {
        CompanyOffices = CompanyOffices ?? new List<Office>();
    }
    public virtual string FullAddress { get; set; }
    public virtual IList<Office> CompanyOffices { get; set; }
}

办公室:

public class Office: Identity
{
    public Office()
    {
        Company = Company ?? new Company();
        Address = Address ?? new Address();
    }
    public virtual Company Company { get; set; }
    public virtual Address Address { get; set; }
    public virtual bool IsHeadOffice { get; set; }
}

现在对于这些类,我有以下映射。

公司映射:

public class CompanyMapping: IdentityMapping<Company>
{
    public CompanyMapping()
    {
        Map(x => x.Name);
        HasMany(x => x.Offices).KeyColumn("CompanyId").Inverse().Cascade.AllDeleteOrphan();
    }
}

地址映射:

public class AddressMapping: IdentityMapping<Address>
{
    public AddressMapping()
    {
        Map(x => x.FullAddress);
        HasMany(x => x.CompanyOffices).KeyColumn("AddressId").Inverse().Cascade.All();
    }
}

办公室映射:

public class OfficeMapping: IdentityMapping<Office>
{
    public OfficeMapping()
    {
        Map(x => x.IsHeadOffice);
        References(x => x.Company).Column("CompanyId").Cascade.None();
        References(x => x.Address).Column("AddressId").Cascade.All();
    }
}

测试代码:

var sessionFactory = CreateSessionFactory();
        using (var session = sessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                var companyOne = new Company { Name = "Company One" };
                var companyTwo = new Company { Name = "Company Two" };

                var addressOne = new Address { FullAddress = "Address One" };
                var addressTwo = new Address { FullAddress = "Address Two" };
                var officeOne = new Office { Company = companyOne, Address = addressOne, IsHeadOffice = true };
                var officeTwo = new Office { Company = companyTwo, Address = addressTwo, IsHeadOffice = false };
                var officeThr = new Office { Company = companyOne, Address = addressTwo, IsHeadOffice = true };

                companyOne.AddOffice(officeOne);
                companyTwo.AddOffice(officeTwo);
                companyOne.AddOffice(officeThr);

                session.SaveOrUpdate(companyOne);
                session.SaveOrUpdate(companyTwo);
                transaction.Commit();
            }
        }

        using (var session = sessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                var companyOne = session.Get<Company>((long)1);
                session.Delete(companyOne);
                transaction.Commit();
            }
        }

代码说明: 在这里,一家公司将拥有多个办事处。 Office与公司和地址之间存在多对多关系,但是由于可能存在许多其他列(Office自己的数据),因此我将关系从多对多更改为2对多。

问题: 我希望我的应用程序删除在删除公司后留下的所有孤立地址。但是在这种情况下,当我删除我的公司时,它也会删除它的地址。但是它不会检查地址是否为孤立地址。如果还有另一个地址参考,它将被删除。按照上面给出的测试代码,它应该删除“公司一”和“地址一”,但不能删除“地址二”,因为它不是孤立的。但是它也会删除“地址二”。

请问有人让我知道 上述映射有什么问题吗?

1 个答案:

答案 0 :(得分:1)

我不确定NHibernate是对DeleteOrphan还是仅对Session进行全局检查,所以真正的全局检查当然会涉及到数据库查询。但这实际上并不相关,DeleteOrphan存在的原因是当您将实体与父对象解除关联时(例如,从集合中删除一个项目然后在父对象上调用Update),但是您正在调用操作直接向下层叠的顶级实体上。

然后真正发生的是,您正在Delete上调用Company,根据Offices上的映射,也就是它的All组件,每个孩子因此,在Offices集合中调用了Delete,因为您在父Delete上调用了Company

由于Office的映射也有一个子项Address,它也映射了All,并且Office刚刚调用了Delete,因此因此,将直接在其Delete的子对象上调用Address,因为直接的Delete不在乎其他关联(除非Session或数据库这样说),只需从数据库中删除Address


如果您无法在此处更改实体结构,则必须停止Delete到达孤立的Address es(首先手动取消关联),或停止Delete级联为{完全{1}},然后完全手动管理Address删除。

我敢肯定,如果您有灵活性的话,有一些更好的实体结构可以更好地处理这些关系:P