如何配置nHibernate的多对多映射? [英] How to configure nHibernate for many-many mapping?

查看:285
本文介绍了如何配置nHibernate的多对多映射?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我有两个业务实体 - Broker Market 。它们分别存储在 brokers markets 表中。我也有 brokerMarkets 表有一个额外的列,名为 MinIncrement 。 Broker和Market之间有很多关系,但仅当我想要存储MinIncrement 值(即它是可选的)时。我的类看起来像这样:

  public class Market:BusinessBase 
{
public Market

public virtual int Id {get;组; }
public virtual string Symbol {get;组; }
public virtual string描述{get;组; }
}

public class Broker:BusinessBase
{
public virtual int Id {get;组; }
public virtual string Name {get;组; }
public virtual bool IsDefault {get;组; }
public virtual bool IsActive {get;组; }
public virtual ISet< Account>帐户{get;组; }


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

public virtual Broker Broker {get;设置;}
public virtual decimal MinIncrement {get;组; }
}



我的映射文件如下所示:
Market.hbm。 xml

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

< class name =MooDB.BusinessLayer.Market,MooDBtable =markets>
< id name =Idcolumn =marketIdtype =Int32unsaved-value =0>
< generator class =native/>
< / id>
< version name =Versioncolumn =versiontype =integerunsaved-value =0/>
< property name =Symbolcolumn =symboltype =Stringlength =10not-null =true/>
< property name =Descriptioncolumn =descriptiontype =Stringlength =30not-null =true/>

< key column =marketId/>
< many-to-many column =brokerIdclass =MooDB.BusinessLayer.Broker,MooDB/>
< / set>
< / class>
< / hibernate-mapping>

Broker.hbm.xml

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

< class name =MooDB.BusinessLayer.Broker,MooDBtable =brokers>
< id name =Idcolumn =brokerIdtype =Int32unsaved-value =0>
< generator class =native/>
< / id>
< version name =Versioncolumn =versiontype =integerunsaved-value =0/>
< property name =Namecolumn =brokertype =Stringlength =50not-null =true/>
< property name =IsActivecolumn =isActivetype =boolnot-null =true/>
< property name =IsDefaultcolumn =isDefaulttype =boolnot-null =true/>

< set name =Marketsgeneric =truetable =brokerMarkets>
< key column =brokerId/>
< many-to-many column =marketIdclass =MooDB.BusinessLayer.Market,MooDB/>
< / set>

< set name =Accountstable =accountsgeneric =trueinverse =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:

  [测试] 
public void CanAddBrokerMarket()
{
Broker broker = _provider.GetBrokerById(1);
Market market = _provider.GetMarketById(2);
变种brokerMarket =新BrokerMarket {经纪人=经纪人,说明= market.Description,符号= market.Symbol,MinIncrement = 0.01M};
_provider.AddBrokerMarket(brokerMarket);
}

当我运行测试时,我得到这个错误:


运行测试。测试
'MooDBTests / MooDB /测试/ DataLayerTests / CanAddBrokerMarket'失败:
信息NHibernate.MappingException:在
NHibernate.Impl
MooDB.BusinessLayer.BrokerMarket堆栈跟踪:没有对于持留.SessionFactoryImpl.GetEntityPersister(字符串
的entityName)在NHibernate.Impl.SessionImpl.GetEntityPersister(字符串
的entityName,对象OBJ)在
NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(对象
实体,字符串的entityName,对象什么,IEventSource源,
布尔requiresImmediateIdAccess)在
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(obj对象)
NHibernateDataProvider.cs(91,0):在
MooDB.DataLayer.NHibernateDataProvider.AddBrokerMarket(BrokerMarket
BM)DataLayerTests.cs(81,0):在
MooDB.Tests.DataLayerTests.CanAddBrokerMarket()


我不知道我做错了什么。我需要在市场课程和市场 Broker c $ c>集合在 Broker 类中?我没有尝试,但我得到了同样的错误,我想我想的东西概念的地方。



更新



我已经实现了以下更改:
Market.hbm.xml

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

< class name =MooDB.BusinessLayer.Market,MooDBtable =markets>
< id name =Idcolumn =marketIdtype =Int32unsaved-value =0>
< generator class =native/>
< / id>
< version name =Versioncolumn =versiontype =integerunsaved-value =0/>
< property name =Symbolcolumn =symboltype =Stringlength =10not-null =true/>
< property name =Descriptioncolumn =descriptiontype =Stringlength =30not-null =true/>
< map name =BrokerMarketstable =brokerMarketslazy =truecascade =none>
< cache usage =read-write/>
< key column =marketId/>
< index column =brokerIdtype =Int32/>
< composite-element class =MooDB.BusinessLayer.BrokerMarket,MooDB>
< parent name =Market/>
< attribute name =MinIncrementcolumn =minIncrementtype =decimal/>
< many-to-one name =Brokerclass =MooDB.BusinessLayer.Broker,MooDBcolumn =brokerId/>
< / composite-element>
< / map>
< / class>
< / hibernate-mapping>

Broker.hbm.xml

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

< class name =MooDB.BusinessLayer.Broker,MooDBtable =brokers>
< id name =Idcolumn =brokerIdtype =Int32unsaved-value =0>
< generator class =native/>
< / id>
< version name =Versioncolumn =versiontype =integerunsaved-value =0/>
< property name =Namecolumn =brokertype =Stringlength =50not-null =true/>
< property name =IsActivecolumn =isActivetype =boolnot-null =true/>
< property name =IsDefaultcolumn =isDefaulttype =boolnot-null =true/>

< set name =Accountstable =accountsgeneric =trueinverse =true>
< key column =brokerId/>
< one-to-many class =MooDB.BusinessLayer.Account,MooDB/>
< / set>
< / class>
< / hibernate-mapping>

市场 class:

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

public virtual int Id {get;组; }
public virtual string Symbol {get;组; }
public virtual string描述{get;组; }
public virtual ISet< BrokerMarket> BrokerMarkets {get;组; } //添加此行
}

BrokerMarket class

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

public virtual Broker Broker {get; set;}
public virtual Market Market {get;组; } //添加此行
public virtual decimal MinIncrement {get;组; }
}

其他都没有改变。我再次运行单元测试,得到:


运行测试。测试
'MooDBTests / MooDB / Tests / DataLayerTests / CanAddBrokerMarket'失败:
在DataLayerTests中测试消息TestFixtureSetUp失败



测试'MooDBTests / MooDB / DataLayerTests'失败:Message SetUp:
NHibernate.MappingException:
集合映射中的重复列:MooDB.BusinessLayer.Market.BrokerMarkets列:brokerId


UPDATE 2



如果我删除



> < code>< index column =brokerIdtype =Int32/>



xml我在运行单元测试时遇到此错误:


运行测试。测试
'MooDBTests / MooDB / Tests / DataLayerTests / CanAddBrokerMarket'失败:
在DataLayerTests中消息TestFixtureSetUp失败



测试'MooDBTests / MooDB / DataLayerTests'失败:Message SetUp:
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,
map-key-many-to-many,index,composite-index,index-many-to-many,
index-many-to-any'in namespace'urn:nhibernate-mapping-2.2'。 ---->
System.Xml.Schema.XmlSchemaValidationException:
命名空间'urn:nhibernate-mapping-2.2'中的元素'map'有无效的子元素
'composite-element' in namespace'urn:nhibernate-mapping-2.2'。
的列表可能的元素列表:'map-key,composite-map-key,
map-key-many-to-many,index,composite-index,index-many-to-many,$



解决方案 b $ b index-many-to-any'in namespace'urn:nhibernate-mapping-2.2' / div>

这个错误可能是因为你没有为BrokerMarket类定义映射,如果你想像你一样保存代理市场,就必须创建BrokerMarket.hbm.xml。你也可以看看使用复合元素在这里像 http://thesoftwaresimpleton.blogspot.com/2010/03/nhibernate-many-to-many-with-extra.html


Using nHibernate 3.2, C# 4.0, SQL Server 2008 R2 Express

I have two business entities - Broker and Market. They are stored in the brokers and markets tables respectively. I also have brokerMarkets table with one extra column called MinIncrement. There's a many-many relationship between Broker and Market, but only when I want to store a MinIncrement value (i.e. it's optional). My classes look like this:

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; }
}

My mapping files look like this: 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>

In my data access layer I have a method to add a BrokerMarket:

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

In my unit test I try and add a BrokerMarket like this:

[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);
}

When I run the test I get this error:

Running the tests. Test 'MooDBTests/MooDB/Tests/DataLayerTests/CanAddBrokerMarket' failed: Message NHibernate.MappingException : No persister for: MooDB.BusinessLayer.BrokerMarket Stack Trace at NHibernate.Impl.SessionFactoryImpl.GetEntityPersister(String entityName) at NHibernate.Impl.SessionImpl.GetEntityPersister(String entityName, Object obj) at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess) at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event) at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event) at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event) at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event) at NHibernate.Impl.SessionImpl.Save(Object obj) NHibernateDataProvider.cs(91,0): at MooDB.DataLayer.NHibernateDataProvider.AddBrokerMarket(BrokerMarket bm) DataLayerTests.cs(81,0): at MooDB.Tests.DataLayerTests.CanAddBrokerMarket()

I'm not sure what I've done wrong. Do I need to add a Broker collection in the Market class and a Market collection in the Broker class? I did try that but I get the same error, and I think I'm missing something conceptually somewhere.

UPDATE

I have implemented the following changes: 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>

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 class:

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 class

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; }
}

Everything else is unchanged. I run the unit test again and I get:

Running the tests. Test 'MooDBTests/MooDB/Tests/DataLayerTests/CanAddBrokerMarket' failed: Message TestFixtureSetUp failed in DataLayerTests

Test 'MooDBTests/MooDB/Tests/DataLayerTests' failed: Message SetUp : NHibernate.MappingException : Repeated column in mapping for collection: MooDB.BusinessLayer.Market.BrokerMarkets column: brokerId

UPDATE 2

If I remove

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

from Market.hbm.xml I get this error when running the unit test:

Running the tests. Test 'MooDBTests/MooDB/Tests/DataLayerTests/CanAddBrokerMarket' failed: Message TestFixtureSetUp failed in DataLayerTests

Test 'MooDBTests/MooDB/Tests/DataLayerTests' failed: Message SetUp : NHibernate.MappingException : MooDB.Mappings.Market.hbm.xml(17,10): XML validation error: The element 'map' in namespace 'urn:nhibernate-mapping-2.2' has invalid child element 'composite-element' in namespace 'urn:nhibernate-mapping-2.2'. List of possible elements expected: 'map-key, composite-map-key, map-key-many-to-many, index, composite-index, index-many-to-many, index-many-to-any' in namespace 'urn:nhibernate-mapping-2.2'. ----> System.Xml.Schema.XmlSchemaValidationException : The element 'map' in namespace 'urn:nhibernate-mapping-2.2' has invalid child element 'composite-element' in namespace 'urn:nhibernate-mapping-2.2'. List of possible elements expected: 'map-key, composite-map-key, map-key-many-to-many, index, composite-index, index-many-to-many, index-many-to-any' in namespace 'urn:nhibernate-mapping-2.2'.

解决方案

the error could be because you have not defined mapping for BrokerMarket Class, If you want to save broker market like the way you are doin will have to create BrokerMarket.hbm.xml. you may also have a look at using composite element here something like http://thesoftwaresimpleton.blogspot.com/2010/03/nhibernate-many-to-many-with-extra.html

这篇关于如何配置nHibernate的多对多映射?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆