2011-07-07 58 views
0

我需要使用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屬性正確水合。它不斷回來作爲一個空列表,但我期望它在列表中有成員,因爲數據庫中有匹配的行。

有什麼建議嗎?我可能做錯了什麼?

+0

似乎你認爲問題出現在Percentages屬性映射中,但問題可能出在BenchmarkFxHedgeRule映射上,該映射沒有問題中顯示的HBM。我會[配置log4net](http://nhforge.org/wikis/howtonh/configure-log4net-for-use-with-nhibernate.aspx)捕獲所有的診斷和SQL映射,以確保正確構建查詢。 –

回答

0

事實證明,問題是我宣佈Percentages集合爲IList而不是ICollection。將聲明更改爲ICollection<BenchmarkFxRuleRatioHistory>可解決問題。