NHibernate:通过PK以外的东西链接集合

时间:2010-09-02 04:32:14

标签: c# database nhibernate nhibernate-mapping

假设我有以下表格:

Company           Person                 Address
----------------------------------------------------------------------------
Id (PK)           Id (PK)                Id (PK)
Name              CompanyId (FK)         CompanyId (FK)
                  AccessType             AddressType

对应于以下C#.NET类:

class Company
{
    int Id;
    List<Person> Employees;
    List<Address> Addresses;
}

class Person
{
    int Id;
    List<Address> CompanyAddresses;
}

class Address
{
    int Id;
    // ...
}

使用NHibernate在公司类上映射Person + Address集合非常容易:

<class name="Company" table="Company">
    <id name="Id" column="Id" />
    <set name="Employees" table="Person">
        <key column="CompanyId" />
        <one-to-many class="Person" />
    </set>
    <set name="Addresses" table="Address">
        <key column="CompanyId" />
        <one-to-many class="Address" />
    </set>
</class>

<class name="Person" table="Person">
    <id name="Id" column="Id" />
</class>

<class name="Address" table="Address">
    <id name="Id" column="Id" />
</class>

我的问题是,如何将地址也映射到Person类?这个想法是,公司有一个人员(员工)和地址(站点)的列表,但公司地址也可以从公司的员工中查找。 (有点奇怪和非正统,我知道,但只是和我一起玩这个)。

通常,我可以通过在Person类地图上定义类似下面的内容来实现这一点:

<set name="CompanyAddresses" table="Address">
    <key column="CompanyId" property-ref="CompanyId" />
</set>

...但是Person(.NET)对象没有为property-ref声明实现一个CompanyId属性来保存水(我们不喜欢它)。

如何通过NHibernate在Person对象中保留一组地址,其中Person :: CompanyId = Address :: CompanyId?

谢谢你们。 :)

修改

这实际上只是像迭戈在下面提到的Person.Company.Addresses映射一样,但遗憾的是,这不会完全奏效,因为公司会有一个地址列表,每个人都链接到一个公司将只有这些地址的子集。

我已经更新了上面的表模式。可以认为,如果Person具有AccessType = ENGINEER,那么只有AddressType = ENGINEERING Addresses将保留在其中(除了CompanyId = CompanyId)。

2 个答案:

答案 0 :(得分:1)

如果你要为一个人存储一个地址,我认为你需要在地址表中找到一些东西链接回Person表。

因此,您可以添加一个PersonId列,并将其用作与人相关的地址的FK

Address
----------
Id (PK)
PersonID (FK - nullable)
CompanyID (FK - nullable)

或者你可以有一个鉴别器列,在这种情况下你的地址表看起来像:

Address
----------
Id (PK)
Owner (Discriminator, eg either "Person" or "Company")
OwnerID (FK)

然后as a Table per Class Hierarchy映射的最自然的方式(我知道),但涉及到PersonAddress和CompanyAddress子类。

答案 1 :(得分:1)

您不应该尝试直接映射它。

由于一个人有一个公司(它在桌子上,我没有在你的映射中看到它,但它应该在那里),获取地址的最简单方法是person.Company.Addresses

如果需要,您可以将其包含在CompanyAddresses属性中,该属性仅委托给Company.Addresses

更新:您可以轻松过滤这些地址,但列表只会是只读的:

public IEnumerable<Address> CompanyAddresses
{
    get { return Company.Addresses.Where(a => a.AddressType == AccessType); }
}