【问题标题】:How to configure nHibernate for many-many mapping with xml files?如何为 xml 文件的多对多映射配置 nHibernate?
【发布时间】:2012-01-10 18:26:49
【问题描述】:

我已经为此苦苦挣扎了一段时间,请参阅我之前的问题How to configure nHibernate for many-many mapping?

我从头开始重新创建了我的项目以试图解决它。我有两个类BrokerInstrument,并且我有一个Broker 和一个Instrument 独有的属性,称为MinIncrement,我需要将其存储在数据库中的多对多映射表中。我创建了一个名为BrokerInstrument 的第三个类来模拟这些额外的信息。这是我的课程的代码:

public abstract class Entity
{
    public virtual int Version {get; private set;}
}

public class Broker : Entity
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual bool IsDefault { get; set; }
    public virtual bool IsActive { get; set; }
    public virtual ISet<BrokerInstrument> BrokerInstruments { get; set; }
}

public class Instrument : Entity
{
    public virtual int Id { get;  set; }
    public virtual string Name { get;  set; }
    public virtual string Symbol {get;  set;}
    public virtual ISet<BrokerInstrument> BrokerInstruments { get; set; }

}

public class BrokerInstrument : Entity
{
    public virtual Broker Broker { get; set; }
    public virtual Instrument Instrument { get; set; }
    public virtual decimal MinIncrement { get; set; }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        var t = obj as BrokerInstrument;
        if (t == null)
            return false;

        if ((Instrument == t.Instrument) && (Broker == t.Broker))
            return true;

        return false;
    }

    public override int GetHashCode()
    {
        return (Broker.Name + "|" + Instrument.Symbol).GetHashCode();            
    }
}

我的映射文件如下所示: Broker.hbm.xml

  <class name="MooDB.Domain.Broker,MooDB" table="brokers">
    <id name="Id" column="brokerId" type="Int32" unsaved-value="0">
      <generator class="native" />
    </id>
    <version name="Version" column="version" type="integer" unsaved-value="0" />
    <property name="Name" column="`name`" type="String" length="50" not-null="true" />
    <property name="IsActive" column="isActive" type="bool" not-null="true" />
    <property name="IsDefault" column="isDefault" type="bool" not-null="true" />
  </class>

仪器.hbm.xml

  <class name="MooDB.Domain.Instrument,MooDB"  table="instruments">
    <id name="Id" column="instrumentId" type="Int32" unsaved-value="0">
      <generator class="native"></generator>
    </id>
    <version name="Version" column="version" type="integer" unsaved-value="0"/>
    <property name="Symbol" column="symbol" type="string" length="10" not-null="false"/>
    <property name="Name" column="`name`" type="string" length="30" not-null="false"/>
  </class>

还有我正在努力解决的映射文件: BrokerInstrument.hbm.xml

  <class name="MooDB.Domain.BrokerInstrument,MooDB"  table="brokerInstruments">
    <composite-id name="BrokerInstrumentIdentifier" class="BrokerInstrument" >
      <key-many-to-one class="Broker" column="brokerId" name="Id" />
      <key-many-to-one class="Instrument" column="instrumentId" name="Id" />
    </composite-id>
    <property name="MinIncrement" column="minIncrement" type="decimal" not-null="true" />
  </class>

我很确定 composite-id 标签中包含的元素是错误的。你知道里面应该放什么吗?另外,我的班级设计看起来是否适合支持此模型?

更新 1

回应科尔的回复。我已经进行了建议的更改,现在我收到了这个错误:

测试“Test.Test.CanAddBrokerInstrument”失败:TestFixtureSetUp 测试失败

TestFixture 失败:NHibernate.PropertyNotFoundException:不能 在类中找到属性“BrokerInstrumentIdentifier”的吸气剂 'MooDB.Domain.BrokerInstrument'

【问题讨论】:

    标签: nhibernate many-to-many


    【解决方案1】:

    这并不是真正的 M:N 关系。这是 3 个实体之间的 M:1 & 1:N 关系。从建模和查询的简单性出发,我会为 BrokerInstrument 分配一个 Id 并一起消除对复合键的需求。

    任何时候你都应该避免复合。这种类型的映射适用于遗留数据库。

    【讨论】:

    • 我倾向于不同意你的观点,杰森,尤其是你答案的最后一行。代理键只会浪费磁盘空间,增加页面大小,从而影响性能。不得不捏造数据库设计以使 ORM 工具完成我需要的工作似乎是不优雅的。多对多关系中的复合主键是良好的数据库设计,而不是您所说的“遗留”。
    • 空间和性能不是避免非复合 PK 与当今技术的有效论据。
    • 我确实按照你的建议让它工作了,尽管它仍然“感觉”错了。我相信我会克服的。
    【解决方案2】:

    key-many-to-one 中的 name 属性应该是 BrokerInstrument 类中对象的属性名称。

    <key-many-to-one class="Broker" column="brokerId" name="Broker" />
    <key-many-to-one class="Instrument" column="instrumentId" name="Instrument" />
    

    编辑:

    <class name="MooDB.Domain.BrokerInstrument,MooDB"  table="brokerInstruments">
        <composite-id>
          <key-many-to-one class="Broker" column="brokerId" name="Broker" />
          <key-many-to-one class="Instrument" column="instrumentId" name="Instrument" />
        </composite-id>
        <property name="MinIncrement" column="minIncrement" type="decimal" not-null="true" />
    </class>
    

    【讨论】:

    • Cole 我更新了我的问题,因为还有一个问题。
    • @MarkAllison 去掉你的composite-id标签中的所有属性。
    • 我很困惑。您是在建议我删除您在答案中发布的行吗?如果这样做,我会收到此错误:“XML 验证错误:命名空间 'urn:nhibernate-mapping-2.2' 中的元素 'composite-id' 内容不完整。”
    • @MarkAllison 不,这不是我的建议。看看我的编辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-12
    • 2011-12-01
    相关资源
    最近更新 更多