使用nHibernate 3.2,C#4.0,SQL Server 2008 R2 Express
我有两个业务实体 - Broker
和Market
。它们分别存储在brokers
和markets
表中。我还有一个名为brokerMarkets
的{{1}}表。 Broker和Market之间有很多关系,但只有当我想存储MinIncrement 值时(即它是可选的)。我的课程看起来像这样:
MinIncrement
我的映射文件如下所示: Market.hbm.xml
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; }
}
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" />
<set name="Brokers" generic="true" table="brokerMarkets">
<key column="marketId" />
<many-to-many column="brokerId" class="MooDB.BusinessLayer.Broker,MooDB" />
</set>
</class>
</hibernate-mapping>
在我的数据访问层中,我有一个添加BrokerMarket的方法:
<?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;
}
}
}
当我运行测试时,我收到此错误:
运行测试。测试 'MooDBTests / MooDB / Tests / DataLayerTests / CanAddBrokerMarket'失败: 消息NHibernate.MappingException:没有持久性: MooDB.BusinessLayer.BrokerMarket Stack Trace at NHibernate.Impl.SessionFactoryImpl.GetEntityPersister(字符串 entityName)at NHibernate.Impl.SessionImpl.GetEntityPersister(String entityName,Object obj)at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(对象 entity,String entityName,Object any,IEventSource source, 布尔值requireImmediateIdAccess)at 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(Object obj) NHibernateDataProvider.cs(91,0):at MooDB.DataLayer.NHibernateDataProvider.AddBrokerMarket(BrokerMarket bm)DataLayerTests.cs(81,0):at MooDB.Tests.DataLayerTests.CanAddBrokerMarket()
我不确定我做错了什么。我是否需要在[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);
}
课程中添加Broker
集合,在Market
课程中添加Market
集合?我确实尝试了但是我得到了同样的错误,我认为我在某处概念性地遗漏了某些东西。
更新
我已实施以下更改: Market.hbm.xml
Broker
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>
<?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
其他一切都没有改变。我再次运行单元测试,然后得到:
运行测试。测试 'MooDBTests / MooDB / Tests / DataLayerTests / CanAddBrokerMarket'失败: 消息TestFixtureSetUp在DataLayerTests中失败
测试'MooDBTests / MooDB / Tests / DataLayerTests'失败:消息设置: NHibernate.MappingException:映射中的重复列 集合:MooDB.BusinessLayer.Market.BrokerMarkets专栏:brokerId
更新2
如果我删除
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'失败:消息设置: 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'innamespace'瓮:nhibernate-mapping-2.2'。 ----&GT; System.Xml.Schema.XmlSchemaValidationException:元素'map'中 namespace'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'。
答案 0 :(得分:0)
错误可能是因为您还没有为BrokerMarket类定义映射,如果您希望像您一样保存代理市场,则必须创建BrokerMarket.hbm.xml。你也可以看一下像http://thesoftwaresimpleton.blogspot.com/2010/03/nhibernate-many-to-many-with-extra.html
那样使用复合元素