C# 在Fluent NHibernate中处理与值类型的一对多关系

C# 在Fluent NHibernate中处理与值类型的一对多关系,c#,nhibernate,fluent-nhibernate,domain-driven-design,C#,Nhibernate,Fluent Nhibernate,Domain Driven Design,我正在将一个应用程序迁移到NHibernate,我正在使用Fluent NHibernate。我遇到了一个将值类型集合映射到聚合根的问题 我有一个PhoneNumber值类型,它有一些属性-Number,NumberType,和Description。我的域中有许多对象都有电话号码的集合 在数据库(SQL 2008)中,这些值保存在不同的表中。因此,我可能有客户和客户电话号码以及供应商和供应商电话号码。除了将电话号码表与其父项关联的外键外,其他电话号码表都是相同的 问题是我想使用一个简单的Pho

我正在将一个应用程序迁移到NHibernate,我正在使用Fluent NHibernate。我遇到了一个将值类型集合映射到聚合根的问题

我有一个
PhoneNumber
值类型,它有一些属性-
Number
NumberType
,和
Description
。我的域中有许多对象都有电话号码的集合

在数据库(SQL 2008)中,这些值保存在不同的表中。因此,我可能有
客户
客户电话号码
以及
供应商
供应商电话号码
。除了将电话号码表与其父项关联的外键外,其他电话号码表都是相同的

问题是我想使用一个简单的
PhoneNumber
值类型,而不必创建
CustomerPhoneNumber
VendorPhoneNumber
类型,这些类型具有与其父类型相关的属性,我不知道如何在NHibernate中实现这一点。这是可能的,还是需要更改域对象以更紧密地匹配底层数据库架构

更新:更多信息
看来我连基本地图都找不到了。以下是我所拥有的一个简化示例:

public class CustomerMap : ClassMap<Customer>
{
    public CustomerMap()
    {
        Table("Customers");

        Id(x => x.Id);
        Map(x => x.Name);
        Component(x => x.Address);
        HasMany(x => x.PhoneNumbers)
            .KeyColumn("CustomerId")
            .Cascade.All()
            .Table("CustomerPhoneNumbers");
    }
}

public class PhoneNumberMap : ClassMap<PhoneNumber>
{
    public PhoneNumberMap()
    {
        Id(x => x.Id);
        Map(x => x.Number, "PhoneNumber");
        Map(x => x.PhoneNumberType);
        Map(x => x.Description);
    }
}
公共类CustomerMap:ClassMap
{
公共客户映射()
{
表(“客户”);
Id(x=>x.Id);
Map(x=>x.Name);
组件(x=>x.Address);
HasMany(x=>x.phonenumber)
.KeyColumn(“客户ID”)
.Cascade.All()
.表格(“客户电话号码”);
}
}
公共类PhoneNumberMap:ClassMap
{
公用电话号码map()
{
Id(x=>x.Id);
Map(x=>x.Number,“PhoneNumber”);
Map(x=>x.PhoneNumberType);
映射(x=>x.Description);
}
}
看起来SQL没有正确生成。当我试图查看客户的电话号码列表时,我得到一个ADO错误,显示NHibernate正在查找一个名为
PhoneNumber
的表


它似乎没有选择
表(“CustomerPhoneNumbers”)
部分,而是默认为与对象名相同的表。然而,我不能在PhoneNumberMap中指定一个表,因为它将根据我们要获取的聚合根而有所不同。

您可以使用entity name mapping属性将单个对象PhoneNumber映射到多个表。对不起,没有示例代码-我不使用Fluent,因此我无法在这方面提供帮助。如果有帮助的话,我可以发布hbm映射示例

实体名称基本上全面取代了类名。使用实体名称时,您还必须修改会话,以便在通过会话处理对象时接受指定实体名称的参数

文件如下:

编辑添加的hbm样本

这将单个对象PhoneNumber映射到多个表

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="DomainModel.PhoneNumber, DomainModel"
    table="PhoneNumberVendors" entity-name="PhoneNumberVendor">
    <id name="_id" access="field" column="PhoneNumberId">
        <generator class="assigned"/>
    </id>
    <property name= "...">
    </class>
<class name="DomainModel.PhoneNumber, DomainModel"
    table="PhoneNumberCustomers" entity-name="PhoneNumberCustomer">
    <id name="_id" access="field" column="PhoneNumberId">
        <generator class="assigned"/>
    </id>
    <property name= "...">
    </class>
</hibernate-mapping>

你必须弄清楚Fluent是否支持这一点,如果支持,怎么做。如果没有,您可以始终将hbm文件用于PhoneNumber对象。

可能需要读取此线程,该线程似乎与复合键有关,因此我不确定这是否适用于此处。目前我最大的问题是,尽管我在map类中为聚合根指定了一个表名,但NHibernate在值类型map类中使用了表名,或者,如果没有表名,假定表名与类名相同。它默认为与对象同名的表名的原因是,您没有在PhoneNumberMap类中指定表(“TableName”)。这并不能解决您必须将多个表映射到同一电话号码对象的问题,但希望有一个解决方案。为仅用于ORM的值对象添加Id更容易,而忽略组件。@Cole,如果我在
PhoneNumberMap
中指定列,它将只使用该表,并且仍然忽略我在聚合根对象中指定的规则。我需要某种方法将单个的
PhoneNumber
类持久化到多个表中-
CustomerPhoneNumber
VendorPhoneNumber
,等等。看起来实体名称更适合我的类,而不是DB,除非我误解了它。而不是作为一般概念的“实体名称”。NHibernate有一个非常特定的属性“entity name”,用于指定NHibernate何时应将单个对象(如电话号码)映射到数据库中的多个表。我在上面添加了示例HBM映射。我的问题是表上的外键不同。我想我可以将它们全部更改为
Parent\u id
,并让NH使用默认值……我从未尝试过,但基于语法,我认为这并不重要。我认为您可以将属性重新映射到不同的列名,因为在每个实体名定义部分中都指定了完整的映射。
_session.Update("PhoneNumberCustomer", myCustomerNumber)