【问题标题】:NHibernate mapping multiple relationshipsNHibernate 映射多个关系
【发布时间】:2016-01-08 04:51:02
【问题描述】:

以下场景的正确 HBM 映射是什么?

我需要将数据库中的 ValueItem 限定为收入或费用项目,以便 NHibernate 在加载时将其加载到正确的列表中。

问题是: 从数据库中检索Container 时,IncomeItems 和 ExpenseItems 集合的内容是相同的。

C#

public class Container
{
    public virtual IList<ValueItem> IncomeItems { get; set; }
    public virtual IList<ValueItem> ExpenseItems { get; set; }
}

public class ValueItem
{
    public virtual double Amount { get; set; }
    public virtual string Description { get; set; }
}

HBM

<class name="Container">
    <id name="Id">
        <generator class="hilo" />
    </id>

    <list name="IncomeItems " cascade="all-delete-orphan">
        <key column="ContainerId" />
        <index column="ItemIndex" />
        <one-to-many class="ValueItem"/>
    </list>

    <list name="ExpenseItems " cascade="all-delete-orphan">
        <key column="ContainerId" />
        <index column="ItemIndex" />
        <one-to-many class="ValueItem"/>
    </list> 
</class>


<class name="ValueItem">
    <id column="Id" type="int">
      <generator class="hilo" />
    </id>

    <property name="Amount" />
    <property name="Description" />
</class>    

【问题讨论】:

  • 看起来应该可以工作,是不是以某种方式不起作用,或者您到底在问什么?
  • @R0MANARMY,问题是两个列表都填充了相同的数据。

标签: c# .net nhibernate nhibernate-mapping


【解决方案1】:

Don on NHUsers 的这个回答解决了我的问题:

唐的回答:

我有一个与你类似的映射,除了我使用包而不是列表,我有 inverse="true",级联设置为默认值,我明确设置表名,每个键都有不同的列名,并且我参考了您的容器,每个容器都有唯一的名称。也许是 inverse=true 或不同 列名。

很抱歉,类名有问题。我当场将它们从 realdomain 对象名称中更改了,我感觉不是很有创意。 希望这会有所帮助,

<class name="Form" >
    <many-to-one name="CreatorPerson" class="Person" />
    <many-to-one name="ProcessorPerson" class="Person" />
</class>

<class name="Person">
    <bag name="FormsCreated" inverse="true">
        <key>
            <column name="CreatorPersonId" not-null="true" />
        </key>
        <one-to-many class="Person" />
    </bag>
    <bag name="FormsToProcess" inverse="true">
        <key>
            <column name="ProcessorPerson" not-null="true" />
        </key>
        <one-to-many class="Person" />
    </bag>
</class> 

【讨论】:

  • 这确实有效。然而,它不是最优雅的解决方案。它为每个列表创建额外的表。在真正的数据库设计中,只有一个鉴别器列。
【解决方案2】:

您可以选择适当的继承策略: http://nhibernate.info/doc/nh/en/index.html#inheritance

或者,如果您的架构无法更改。您可以在列表映射中指定where 属性。这些将指定如何获取它们。

【讨论】:

  • 我想用继承来解决它,但这似乎是把它强加到一些并不真正需要它的东西上。在这种情况下,where 子句会是什么,这两个项目之间没有什么区别?我可以在 C# 端区分,但不能在 DB 上区分。可以在映射中添加具有默认值的属性,然后在哪里添加?
  • @Philip 如果在数据库端无法区分,NHibernate 也无法为您做到。请记住,它仍然是数据库的接口。
  • 再次感谢您的回复。我理解你的说法。我想知道是否可以提供类似于 NHibernate 中用于子类分类的鉴别器的映射。通过子类化,NHibernate 提供了进一步“装饰”表格以指示类型的能力。显然我不想在这里子类化,因为它不是必需的。这是一种常见的模式,必须有一种简单的方法来实现这一点。顺便说一句,我知道它是数据库的接口。
  • @Philip,子类化 NHibernate 不会装饰表格。该表仍然需要一个鉴别器列,用于确定类型。因此,如果您不能提供一个 sql 查询来区分收入项目与费用项目,那么 NHibernate 也将无法做到这一点。如果您可以区分它们的唯一方法是通过代码,您可以创建包含所有项目的私有字段和能够区分项目、添加新项目等的公共访问器属性/方法。
  • @Philip Fourie:在这种情况下,如果您想确保记录不会从“收入”集合中取出然后重新插入“费用”列,那么您可能会受益于子类化。至少在收入和支出方面,我想不出这样的交易有效的理由。使用子类,您可以确保它们在物理上是不同的类型,并且尝试这样做的代码不会编译。
猜你喜欢
  • 2012-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多