Как настроить nHibernate для сопоставления многие-многие? - PullRequest
2 голосов
/ 07 января 2012

Использование nHibernate 3.2, C # 4.0, SQL Server 2008 R2 Express

У меня есть две бизнес-сущности - Broker и Market.Они хранятся в таблицах brokers и markets соответственно.У меня также есть таблица brokerMarkets с одним дополнительным столбцом, который называется MinIncrement.Существует много-много отношений между брокером и рынком, но только тогда, когда я хочу сохранить значение MinIncrement (т.е. это необязательно).Мои классы выглядят так:

public class Market : BusinessBase
{
    public Market() {}

    public virtual int Id { get; set; }
    public virtual string Symbol { get; set; }
    public virtual string Description { get; set; }
}

public class Broker : BusinessBase
{
    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<Account> Accounts { get; set; }
}

public class BrokerMarket : Market
{
    public BrokerMarket() { }

    public virtual Broker Broker {get; set;}
    public virtual decimal MinIncrement { get; set; }
}

Мои файлы сопоставления выглядят так: Market.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="MooDB"
                   namespace="MooDB.BusinessLayer">

    <class name="MooDB.BusinessLayer.Market,MooDB" table="markets">
        <id name="Id" column="marketId" type="Int32" unsaved-value="0">
            <generator class="native" />
        </id>           
        <version name="Version" column="version" type="integer" unsaved-value="0" />
        <property name="Symbol" column="symbol" type="String" length="10" not-null="true" />
        <property name="Description" column="description" type="String" length="30" not-null="true" />

        <set name="Brokers" generic="true" table="brokerMarkets">
            <key column="marketId" />
            <many-to-many column="brokerId" class="MooDB.BusinessLayer.Broker,MooDB" />            
        </set>
    </class>
</hibernate-mapping>

Broker.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="MooDB"
                   namespace="MooDB.BusinessLayer">

    <class name="MooDB.BusinessLayer.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="broker" 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" />

        <set name="Markets" generic="true" table="brokerMarkets">
            <key column="brokerId" />
            <many-to-many column="marketId" class="MooDB.BusinessLayer.Market,MooDB" />
        </set>

        <set name="Accounts" table="accounts" generic="true" inverse="true">
            <key column="brokerId" />
            <one-to-many class="MooDB.BusinessLayer.Account,MooDB" />
        </set>
    </class>    
</hibernate-mapping>

В моем слое доступа к данным у меня есть метод для добавления BrokerMarket:

public void AddBrokerMarket(BrokerMarket bm)
{
    using (ITransaction tx = _session.BeginTransaction())
    {
        try
        {
            _session.Save(bm);
            _session.Flush();
            tx.Commit();
        }
        catch (HibernateException)
        {
            tx.Rollback();
            throw;
        }
    }
}

В моем модульном тесте я пытаюсь добавить BrokerMarket следующим образом:

[Test]
public void CanAddBrokerMarket()
{
    Broker broker = _provider.GetBrokerById(1);
    Market market = _provider.GetMarketById(2);
    var brokerMarket = new BrokerMarket { Broker = broker, Description = market.Description, Symbol = market.Symbol, MinIncrement = 0.01M };
    _provider.AddBrokerMarket(brokerMarket);
}

Когда я запускаю тестЯ получаю эту ошибку:

Запуск тестов.Не удалось выполнить тест «MooDBTests / MooDB / Tests / DataLayerTests / CanAddBrokerMarket»: Сообщение NHibernate.MappingException: нет сохранения для: MooDB.BusinessLayer.BrokerMarket Трассировка стека в NHibernate.Impl.SessionFactoryImpl.GestlImpImpityImpityImpityImpityImpityImpityImpityImpityImpitySP_ImpityImpityImpityImpitySityGerityPity_ImpSignity.Imp_Player(String entityName, Object obj) в NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId (Объектный объект, String entityName, Объект что-нибудь, источник IEventSource, логическое значение requireImmediateIdAccess) в NHibernate.Event.Default.DefaultSaveOventWeventOventEventWeventOventEventLeventOventEventLeventOventEventLeventOventEventLeventOventEventLeventOventEventLeventOventEventLeventOventEventLeventEventLventWvent) СобытиеEvent.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId (SaveOrUpdateEvent событие) в NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient (событие SaveOrUpdateEvent) на NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate (событие SaveOrUpdateEvent) в NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate (событие SaveOrUpdateEvent) в NHibernate.Impl.SessionImpl.FireSave (событие SaveOrUpdateEvent) в NHibernate.Impl.SessionImpl.Save (объектный объект) NHibernateDataProvider.cs (91,0) :BarkDerbBerBDBMDBDBDBDBDBDBDBDBDBDBDBRID_BRID_BRK_D_WR_D_WR_D_D_D_D_D_D_D_D_W_R_P_M_D_D_W_R_P_P_P_M_D_D_P_P_M_D_P_P_P_P_P_P_RUDataLayerTests.cs (81,0): в MooDB.Tests.DataLayerTests.CanAddBrokerMarket ()

Я не уверен, что я сделал неправильно.Нужно ли добавлять коллекцию Broker в классе Market и коллекцию Market в классе Broker?Я пробовал это, но я получаю ту же ошибку, и я думаю, что где-то что-то концептуально отсутствует.

ОБНОВЛЕНИЕ

Я внес следующие изменения: Рынок.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="MooDB"
                   namespace="MooDB.BusinessLayer">

    <class name="MooDB.BusinessLayer.Market,MooDB" table="markets">
        <id name="Id" column="marketId" type="Int32" unsaved-value="0">
            <generator class="native" />
        </id>           
        <version name="Version" column="version" type="integer" unsaved-value="0" />
        <property name="Symbol" column="symbol" type="String" length="10" not-null="true" />
        <property name="Description" column="description" type="String" length="30" not-null="true" />
      <map name="BrokerMarkets" table="brokerMarkets" lazy="true" cascade="none">
        <cache usage="read-write"/>
        <key column="marketId" />
        <index column="brokerId" type="Int32" />
        <composite-element class="MooDB.BusinessLayer.BrokerMarket,MooDB">
          <parent name="Market"/>
          <property name="MinIncrement" column="minIncrement" type="decimal" />
          <many-to-one name="Broker" class="MooDB.BusinessLayer.Broker,MooDB" column="brokerId" />
        </composite-element>        
      </map>
    </class>
</hibernate-mapping>

Broker.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="MooDB"
                   namespace="MooDB.BusinessLayer">

    <class name="MooDB.BusinessLayer.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="broker" 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" />

        <set name="Accounts" table="accounts" generic="true" inverse="true">
            <key column="brokerId" />
            <one-to-many class="MooDB.BusinessLayer.Account,MooDB" />
        </set>
    </class>    
</hibernate-mapping>

Market класс:

public class Market : BusinessBase
{
    public Market() {}

    public virtual int Id { get; set; }
    public virtual string Symbol { get; set; }
    public virtual string Description { get; set; }
    public virtual ISet<BrokerMarket> BrokerMarkets { get; set; } //added this line
}

BrokerMarket класс

public class BrokerMarket : Market
{
    public BrokerMarket() { }

    public virtual Broker Broker {get; set;}
    public virtual Market Market { get; set; } // added this line
    public virtual decimal MinIncrement { get; set; }
}

Все остальное без изменений.Я снова запускаю тестовый модуль и получаю:

Запуск тестов.Сбой теста 'MooDBTests / MooDB / Tests / DataLayerTests / CanAddBrokerMarket': Ошибка TestFixtureSetUp в DataLayerTests

Сбой теста 'MooDBTests / MooDB / Tests / DataLayerTests': MooDB.BusinessLayer.Market.BrokerMarkets столбец: brokerId

ОБНОВЛЕНИЕ 2

Если я удаляю

<index column="brokerId" type="Int32" />

из Market.hbm.xml Я получаю эту ошибку при запуске модульного теста:

Запуск тестов.Test 'MooDBTests / MooDB / Тесты / DataLayerTests / CanAddBrokerMarket' не удалось: Сообщение TestFixtureSetUp неудачу в DataLayerTests

1077 * 'MooDBTests / MooDB / Тесты / DataLayerTests' Test Failed: нАлАдкА Сообщение: NHibernate.MappingException: MooDB.Mappings.Market.hbm.xml (17,10): Ошибка проверки XML: элемент 'map' в пространстве имен 'urn: nhibernate-mapping-2.2' имеет недопустимый дочерний элемент 'составной-элемент' в пространстве имен 'urn: nhibernate-mapping-2.2'.Список возможных ожидаемых элементов: 'ключ-карта, составной-ключ-карта,индекс-ключ-многие-ко-многим, индекс, составной-индекс, индекс-многие-ко-многим, index-many-to-any 'в пространстве имен' urn: nhibernate-mapping-2.2 '. ----> System.Xml.Schema.XmlSchemaValidationException: элемент 'map' в пространство имен 'urn: nhibernate-mapping-2.2' имеет недопустимый дочерний элемент «составной элемент» в пространстве имен «urn: nhibernate-mapping-2.2». Список ожидаемые возможные элементы: 'ключ-карта, составной-ключ-карта, индекс-ключ-многие-ко-многим, индекс, составной-индекс, индекс-многие-ко-многим, index-many-to-any 'в пространстве имен' urn: nhibernate-mapping-2.2 '.

1 Ответ

0 голосов
/ 07 января 2012

ошибка может быть связана с тем, что вы не определили сопоставление для класса BrokerMarket. Если вы хотите сохранить рынок брокеров, как вы это делаете, вам придется создать BrokerMarket.hbm.xml. Вы также можете взглянуть на использование составного элемента здесь что-то вроде http://thesoftwaresimpleton.blogspot.com/2010/03/nhibernate-many-to-many-with-extra.html

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