如何为多映射配置nHibernate

本文关键字:配置 nHibernate 映射 | 更新日期: 2023-09-27 18:19:44

使用nHibernate 3.2、C#4.0、SQL Server 2008 R2 Express

我有两个业务实体——BrokerMarket。它们分别存储在brokersmarkets表中。我还有一个brokerMarkets表,它有一个额外的列,叫做MinIncrement。Broker和Market之间有很多关系,但只有当我想存储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>

经纪人.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.GetEntityPersister(字符串entityName)在NHibernate.Impl.SessionImpl.GetEntityPersister(字符串entityName,Object obj)NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(对象entity,String entityName,Object anything,IEventSource source,在处需要布尔值ImmediateIdAccess)NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent事件)NHibernate.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):位于MooDB.DataLayer.NHibernateDataProvider.AddBrokerMarket(经纪市场bm)DataLayerTests.cs(81,0):位于MooDB.Tests.DataLayerTests.CanAddBrokerMarket()

我不确定我做错了什么。我需要在Market类中添加一个Broker集合,在Broker类中添加Market集合吗?我确实试过了,但我也犯了同样的错误,我想我在概念上遗漏了一些东西。

更新

我已经实施了以下更改: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" />
      <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>

经纪人.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"失败:DataLayerTests 中的Message TestFixtureSetUp失败

测试"MooDBTests/MooDB/Tests/DataLayerTests"失败:消息设置:NHibernate.MappingException:的映射中重复列收藏:MooDB.BusinessLayer.Market.BrokerMarkets专栏:brokerId

更新2

如果我删除

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

在Market.hbm.xml中,我在运行单元测试时收到了以下错误:

正在运行测试。测验"MooDBTests/MooDB/Tests/DataLayerTests/CanAddBrokerMarket"失败:DataLayerTests 中的Message TestFixtureSetUp失败

测试"MooDBTests/MooDB/Tests/DataLayerTests"失败:消息设置:NHibernate.MappingException:MooDB.Mappings.Market.hbm.xml(17,10):XML验证错误:命名空间中的元素"map"urn:nhibernate-mapping-2.2"具有无效的子元素命名空间"urn:nhibernate-mapping-2.2"中的"composite element"。的列表需要可能的元素:'map key,composite map key,映射键多对多,索引,复合索引,索引多对多,将many索引到命名空间'urn:nhibernate-mapping-2.2'中的任意'---->System.Xml.Schema.XmlSchemaValidationException:中的元素"map"命名空间"urn:nhibernate-mapping-2.2"具有无效的子元素命名空间"urn:nhibernate-mapping-2.2"中的"composite element"。的列表需要可能的元素:'map key,composite map key,映射键多对多,索引,复合索引,索引多对多,将多个索引到命名空间"urn:nhibernate-mapping-2.2"中的任意"。

如何为多映射配置nHibernate

错误可能是因为您没有定义BrokerMarket类的映射。如果您想像现在这样保存BrokerMarket,则必须创建BrokerMarket.hbm.xmlhttp://thesoftwaresimpleton.blogspot.com/2010/03/nhibernate-many-to-many-with-extra.html