首页 文章

NHibernate:为什么要使用<composite-element>而不是<one-to-many>来映射集合

提问于
浏览
8

使用NHibernate时,在什么情况下你会选择使用复合元素映射集合来给出一组值对象,而不是创建一个完整的实体并使用一对多映射它?

您可能有一个值类型类'PostalAddress'来表示地址 . 如果您有一个人实体,并且每个人可以拥有许多地址,您可以像这样映射这种关系(选项1):

<bag name="Addresses" table="PersonAddress">
    <key column="PersonID"/>
    <composite-element class="PostalAddress">
        <property name="StreetAddress"/>
        <property name="Town"/>
        <property name="City"/>
        <property name="Postcode"/>
    </composite-element>
</bag>

或者您可以创建一个实体“PersonAddress”,其上有一个“PostalAddress”类型的属性,并使用一对多关联映射地址(选项2):

<bag name="Addresses">
    <key column="PersonID"/>
    <one-to-many class="PersonAddress"/>
</bag>

<class name="PersonAddress">

    <id name="Id">
        <generator class="native"/>
    </id>

    <component name="Address" class="PostalAddress">
        <property name="StreetAddress"/>
        <property name="Town"/>
        <property name="City"/>
        <property name="Postcode"/>
    </component>

</class>

是否有任何理由不做选项1? PersonAddress表有ID列的事实是否应该是一个实体本身,因此使用选项2?

1 回答

  • 19

    <composite-element>适用于具有值集合的情况,而<one-to-many>是实体集合 . 实体的定义特征是唯一标识符 . 因此,如果集合中的项目具有PK,请使用<one-to-many> . 否则使用<composite-element> .

    另一种思考方式是如何确定平等 . 您是通过比较ID还是通过验证所有属性是否相同来确定相等性?例如在你的应用程序中,如果(address1.Id == address2.Id)或if(address1.Street == address2.Street && address1.City == address2.City && etc.等),两个对象是否代表相同的地址?没有通用的正确答案,因为它取决于应用程序上下文 . 在许多情况下,金钱是一个 Value 对象 . 无论你有20美元还是20美元,都没关系 . 只有金额是相关的 . 如果您正在为薄荷编写跟踪应用程序,他们可能需要知道您正在处理哪个20美元的账单,并且您将在20美元的账单上跟踪序列号 . 在这种情况下,货币是一个实体 . 这完全取决于应用和背景......

相关问题