I’ve been struggling with this for a while see my previous question How to configure nHibernate for many-many mapping?
I have recreated my project from scratch in an attempt to solve it. I have two classes Broker and Instrument and I have a property unique to a Broker and an Instrument called MinIncrement that I need to store in my many-many mapping table in the database. I created a third class called BrokerInstrument to model this extra information. Here is the code for my classes:
public abstract class Entity
{
public virtual int Version {get; private set;}
}
public class Broker : Entity
{
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<BrokerInstrument> BrokerInstruments { get; set; }
}
public class Instrument : Entity
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Symbol {get; set;}
public virtual ISet<BrokerInstrument> BrokerInstruments { get; set; }
}
public class BrokerInstrument : Entity
{
public virtual Broker Broker { get; set; }
public virtual Instrument Instrument { get; set; }
public virtual decimal MinIncrement { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
return false;
var t = obj as BrokerInstrument;
if (t == null)
return false;
if ((Instrument == t.Instrument) && (Broker == t.Broker))
return true;
return false;
}
public override int GetHashCode()
{
return (Broker.Name + "|" + Instrument.Symbol).GetHashCode();
}
}
My mapping files look like this:
Broker.hbm.xml
<class name="MooDB.Domain.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="`name`" 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" />
</class>
Instrument.hbm.xml
<class name="MooDB.Domain.Instrument,MooDB" table="instruments">
<id name="Id" column="instrumentId" type="Int32" unsaved-value="0">
<generator class="native"></generator>
</id>
<version name="Version" column="version" type="integer" unsaved-value="0"/>
<property name="Symbol" column="symbol" type="string" length="10" not-null="false"/>
<property name="Name" column="`name`" type="string" length="30" not-null="false"/>
</class>
And the mapping file I’m struggling with:
BrokerInstrument.hbm.xml
<class name="MooDB.Domain.BrokerInstrument,MooDB" table="brokerInstruments">
<composite-id name="BrokerInstrumentIdentifier" class="BrokerInstrument" >
<key-many-to-one class="Broker" column="brokerId" name="Id" />
<key-many-to-one class="Instrument" column="instrumentId" name="Id" />
</composite-id>
<property name="MinIncrement" column="minIncrement" type="decimal" not-null="true" />
</class>
I’m pretty sure the elements enclosed within composite-id tags are wrong. Do you know what should go in there? Also, does my class design look right to support this model?
UPDATE 1
In response to Cole’s reply. I have made the change suggested and I now get this error:
Test ‘Test.Test.CanAddBrokerInstrument’ failed: TestFixtureSetUp
failed in TestTestFixture failed: NHibernate.PropertyNotFoundException : Could not
find a getter for property ‘BrokerInstrumentIdentifier’ in class
‘MooDB.Domain.BrokerInstrument’
this isn’t really an M:N relationship. it’s a M:1 & 1:N relationships between 3 entities. From simplicity of modeling and queries I would assign an Id to BrokerInstrument and remove the need for a composite key all together.
anytime you can avoid composite you should. this type of mapping is for legacy databases.