Проблема с отображением «один ко многим» с использованием составных ключей - PullRequest
0 голосов
/ 07 июля 2011

У меня есть две таблицы в устаревшей базе данных, которые мне нужно отобразить с помощью 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 голосов
/ 08 июля 2011

Оказывается, проблема была в том, что я объявил коллекцию Percentages как IList вместо ICollection.Изменение объявления на ICollection<BenchmarkFxRuleRatioHistory> решает проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...