使用复合键进行一对多映射的问题

时间:2011-07-07 11:25:49

标签: nhibernate

我在遗留数据库中有两个表,我需要使用NHibernate进行映射。不幸的是,其中一个表正在使用复合键,我遇到了一个我在下面描述的问题。

首先,这是两个表的模式:

CREATE TABLE [dbo].[tBenchmarkFxHedgeHistory](
    [BenchmarkFxHedgeHistoryId] [int] IDENTITY(1,1) NOT NULL,
    [BenchmarkFxHedgeId] [int] NOT NULL,
    [ModelId] [int] NOT NULL,
    [BaseCurrencyCode] [nvarchar](5) NOT NULL,
    [BenchmarkFxHedgeTypeId] [int] NOT NULL,
    [DateFrom] [smalldatetime] NOT NULL,
    [DateTo] [smalldatetime] NULL,
    [PctHedgeBackToBase] [decimal](13, 10) NULL,
    [Enabled] [bit] NOT NULL,
    [BenchmarkHedgeStatusId] [int] NOT NULL,
    [AuditActionId] [int] NOT NULL,
    [Timestamp] [timestamp] NOT NULL,
    [HistoryUser] [nvarchar](50) NOT NULL CONSTRAINT [DF_tBenchmarkFxHedgeHistory_HistoryUser]  DEFAULT (suser_sname()),
    [HistoryDate] [datetime] NOT NULL CONSTRAINT [DF_tBenchmarkFxHedgeHistory_HistoryDate]  DEFAULT (getdate()),
 CONSTRAINT [PK_tBenchmarkFxHedgeHistory] PRIMARY KEY CLUSTERED 
(
    [BenchmarkFxHedgeHistoryId] ASC
)

CREATE TABLE [dbo].[tBenchmarkFxHedgeRatio](
    [BenchMarkFxHedgeId] [int] NOT NULL,
    [NonBaseCurrencyCode] [nvarchar](5) NOT NULL,
    [PctHedgeBackToBase] [decimal](13, 10) NOT NULL,
 CONSTRAINT [PK_tBenchmarkFxHedgeRatio] PRIMARY KEY CLUSTERED 
(
    [BenchMarkFxHedgeId] ASC,
    [NonBaseCurrencyCode] ASC
)

以下是域类:

public class BenchmarkFxHedgeRuleHistory 
{
    private IList<BenchmarkFxRuleRatioHistory> _percentages = new List<BenchmarkFxRuleRatioHistory>();

    public virtual int Id { get; set; }
    public virtual string BaseCurrencyCode { get; set; }
    public virtual DateTime DateFrom { get; set; }
    public virtual DateTime? DateTo { get; set; }
    public virtual decimal? Percentage { get; set; }
    public virtual bool Enabled { get; set; }
    public virtual byte[] Timestamp { get; set; }
    public virtual BenchmarkFxHedgeStatus Status { get; set; }
    public virtual BenchmarkFxHedgeType Strategy { get; set; }
    public virtual Model Model { get; set; }
    public virtual BenchmarkFxHedgeRule Rule { get; set; }
    public virtual AuditAction AuditAction { get; set; }

    public virtual IList<BenchmarkFxRuleRatioHistory> Percentages
    {
        get { return _percentages; }
    }
}

[Serializable]
public class BenchmarkFxRuleRatioHistory
{
    public virtual string NonBaseCurrencyCode { get; set; }
    public virtual decimal Percentage { get; set; }
    public virtual BenchmarkFxHedgeRuleHistory HistoryEntry { get; set; }

    public override bool Equals(object obj)
    {
        var rule = obj as BenchmarkFxRuleRatioHistory;
        if (rule == null) return false;
        return rule.HistoryEntry.Id == HistoryEntry.Id && NonBaseCurrencyCode == rule.NonBaseCurrencyCode;
    }

    public override int GetHashCode()
    {
        return NonBaseCurrencyCode.GetHashCode() ^ HistoryEntry.GetHashCode();
    }
}

最后,这里是NHibernate映射文件:

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping namespace="Tests.DomainModel" assembly="Tests.DomainModel" xmlns="urn:nhibernate-mapping-2.2">
    <class name="BenchmarkFxHedgeRuleHistory" table="`tBenchmarkFxHedgeHistory`" schema="`dbo`">
        <id name="Id" access="property" column="`BenchmarkFxHedgeHistoryId`">
            <generator class="native" />
        </id>
    <many-to-one name="Rule" class="BenchmarkFxHedgeRule" column="`BenchmarkFxHedgeId`" not-null="true" fetch="select" />
        <property name="BaseCurrencyCode" type="String" column="`BaseCurrencyCode`" length="5" />
        <property name="DateFrom" type="DateTime" column="`DateFrom`" />
        <property name="DateTo" type="DateTime" column="`DateTo`" />
        <property name="Enabled" type="Boolean" column="`Enabled`" />
        <property name="Percentage" type="Decimal" column="`PctHedgeBackToBase`" />
        <property name="Timestamp" type="BinaryBlob" column="`Timestamp`" />
        <many-to-one name="Status" class="BenchmarkFxHedgeStatus" column="`BenchmarkHedgeStatusId`" not-null="true" fetch="join" />
    <many-to-one name="Strategy" class="BenchmarkFxHedgeType" column="`BenchmarkFxHedgeTypeId`" not-null="true" fetch="join" />
        <many-to-one name="Model" class="Model" column="`ModelId`" not-null="true" fetch="select" />
    <many-to-one name="AuditAction" class="AuditAction" column="`AuditActionId`" not-null="true" fetch="join" />
    <bag name="Percentages" fetch="join" access="readonly" inverse="true" lazy="false" table="tBenchmarkFxHedgeRatioHistory" cascade="all-delete-orphan" subselect="">
      <key column="`BenchmarkFxHedgeHistoryId`" />
      <one-to-many class="BenchmarkFxRuleRatioHistory" />
    </bag>
    </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping namespace="Tests.DomainModel" assembly="Tests.DomainModel" xmlns="urn:nhibernate-mapping-2.2">
    <class name="BenchmarkFxRuleRatioHistory" table="`tBenchmarkFxHedgeRatioHistory`" schema="`dbo`">
    <composite-id>
      <key-property name="NonBaseCurrencyCode" type="String" column="`NonBaseCurrencyCode`" />
      <key-many-to-one name="HistoryEntry" class="BenchmarkFxHedgeRuleHistory" column="`BenchmarkFxHedgeHistoryId`" />
    </composite-id>
    <property name="Percentage" type="decimal" column="`PctHedgeBackToBase`" />
    </class>
</hibernate-mapping>

现在我在以下代码中使用这些:

using(var session = DataMapperConfiguration.SessionFactory.OpenSession())
{
    var sessionRule = session.Get<BenchmarkFxHedgeRule>(id);
    var historyList = session.Query<BenchmarkFxHedgeRuleHistory>()
        .Where(x => x.Rule == sessionRule).ToList();
    Assert.AreEqual(2, historyList[0].Percentages.Count);
}

sessionRule正确补充水分,但historyList没有正确补充Percentages属性。它一直作为空列表返回,但我希望它在列表中有成员,因为数据库中有匹配的行。

有什么建议吗?我能做错什么?

1 个答案:

答案 0 :(得分:0)

事实证明问题在于我将Percentages集合声明为IList而不是ICollection。将声明更改为ICollection<BenchmarkFxRuleRatioHistory>可以解决问题。