NHibernate删除多对多父级和子级

NHibernate删除多对多父级和子级,nhibernate,fluent-nhibernate,nhibernate-mapping,fluent-nhibernate-mapping,Nhibernate,Fluent Nhibernate,Nhibernate Mapping,Fluent Nhibernate Mapping,我有三节课公司,地址和办公室。以下是实体定义 公司: 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 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();
            }
        }
现在,对于这些类,我有以下映射

公司映射:

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();
            }
        }
公共类公司映射:标识映射
{
上市公司映射()
{
Map(x=>x.Name);
HasMany(x=>x.Offices).KeyColumn(“CompanyId”).Inverse().Cascade.AllDeleteOrphan();
}
}
地址映射:

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();
            }
        }
public类地址映射:IdentityMapping
{
公共地址映射()
{
映射(x=>x.FullAddress);
HasMany(x=>x.CompanyOffices).KeyColumn(“AddressId”).Inverse().Cascade.All();
}
}
办公室映射:

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();
            }
        }
公共类OfficeMapping:IdentityMapping
{
公职申请
{
地图(x=>x.ishadoffice);
引用(x=>x.Company).Column(“CompanyId”).Cascade.None();
引用(x=>x.Address).Column(“AddressId”).Cascade.All();
}
}
测试代码:

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();
            }
        }
var sessionFactory=CreateSessionFactory();
使用(var session=sessionFactory.OpenSession())
{
使用(var transaction=session.BeginTransaction())
{
var companyOne=新公司{Name=“companyOne”};
var companyTwo=新公司{Name=“companyTwo”};
var addressOne=新地址{FullAddress=“地址一”};
var addressTwo=新地址{FullAddress=“Address Two”};
var officeOne=new Office{Company=companyOne,Address=addressOne,ishadoffice=true};
var officeTwo=新办公室{Company=companyTwo,Address=addressTwo,ishadoffice=false};
var officehr=新办公室{Company=companyOne,Address=addressTwo,ishadoffice=true};
公司地址:办公室(officeOne);
公司2.地址办公室(办公室2);
公司地址办公室(人力资源办公室);
会话。保存或更新(公司名称);
会话.保存或更新(公司2);
Commit();
}
}
使用(var session=sessionFactory.OpenSession())
{
使用(var transaction=session.BeginTransaction())
{
var companyOne=session.Get((long)1);
删除(公司名称);
Commit();
}
}
代码说明: 在这里,一家公司将有多个办公室。Office是公司和地址的多对多关系,但由于可能有许多其他列(Office自己的数据),我已将关系从多对多更改为2对1对多

问题: 我希望我的应用程序删除任何在公司被删除时留下的孤立地址。但在这种情况下,当我删除我的公司时,它也会删除它的地址。但它不会检查地址是否为孤立地址。如果有另一个地址引用,它仍将被删除。根据上述测试代码,应删除“公司一号”和“地址一号”,但不删除“地址二号”,因为它不是孤立的。但它也删除了“地址二”


有谁能告诉我上面的映射有什么问题吗?

我不确定NHibernate是对
删除孤儿进行全局检查,还是只对
会话进行检查,真正的全局检查当然会涉及DB查询。但这实际上与此处无关,
DeleteOrphan
存在的原因是当您解除实体与父实体的关联(例如,从集合中删除一个项目,然后调用父实体上的
Update
),但您调用的是直接向下层叠的顶级实体上的操作

然后真正发生的事情是,您正在调用
Offices
上的
Delete
,根据
Offices
上的映射,即
All
组件,因此
Offices
集合中的每个孩子都调用了
Delete
,因为您在母公司
公司
上调用了
Delete

由于
Office
的映射也有一个子
Address
,该子
Address也映射为
All
,并且
Office
刚刚调用了
Delete
,因此它将直接在它的
Address
子对象上调用
Delete
,由于直接
删除
不关心其他关联(除非
会话
或DB这样说),因此只需从DB中删除
地址


如果您无法在此处更改实体结构,则您必须停止
删除
到达未注册的
地址
es(首先手动解除它们的关联),或者停止
删除
级联到
地址
,然后完全手动管理
地址
删除

我相信如果你有灵活性的话,有一些更好的实体结构可以更好地处理这些关系:p