我有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对多。
问题: 我希望我的应用程序删除在删除公司后留下的所有孤立地址。但是在这种情况下,当我删除我的公司时,它也会删除它的地址。但是它不会检查地址是否为孤立地址。如果还有另一个地址参考,它将被删除。按照上面给出的测试代码,它应该删除“公司一”和“地址一”,但不能删除“地址二”,因为它不是孤立的。但是它也会删除“地址二”。
请问有人让我知道 上述映射有什么问题吗?
答案 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