Hi all!
NHibernate version: 0.8.4.0
Database: Firebird (embeded)
.NET Version: 1.1
I have 3 tables: Competitor, Tournament, Result
Competitor:
Code:
CREATE TABLE COMPETITOR (
COMPETITORID INTEGER NOT NULL,
NAME VARCHAR(50) NOT NULL,
PRIMARY KEY (COMPETITORID);
);
TournamentCode:
CREATE TABLE TOURNAMENT(
TOURNAMENTID INTEGER NOT NULL,
NAME VARCHAR(50) NOT NULL,
PRIMARY KEY (TOURNAMENTID)
);
Result:Code:
CREATE TABLE RESULT (
COMPETITORID INTEGER NOT NULL,
TOURNAMENTID INTEGER NOT NULL,
RESULT INTEGER NOT NULL,
PRIMARY KEY (COMPETITORID, TOURNAMENTID),
FOREIGN KEY (COMPETITORID) REFERENCES COMPETITOR (COMPETITORID) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (TOURNAMENTID) REFERENCES TOURNAMENT (TOURNAMENTID) ON DELETE CASCADE ON UPDATE CASCADE;
);
As you can see the result table has a 2 field primary key with a additional result field so I can't use many-to-many!
So I came up with:
competitor.hbm.xmlCode:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" namespace="HrvatskaStrijela.Database.Entities"
assembly="HrvatskaStrijela.Database">
<class name="HrvatskaStrijela.Database.Entities.CompetitorEntity, HrvatskaStrijela.Database" table="COMPETITOR">
<id name="CompetitorId" column="COMPETITORID" type="Int32">
<generator class="native">
<param name="sequence">GEN_COMPETITOR_ID</param>
</generator>
</id>
<property name="Name" type="string" not-null="true"/>
<bag name="Results" cascade="all" lazy="true" inverse="true">
<key column="COMPETITORID" />
<one-to-many class="HrvatskaStrijela.Database.Entities.ResultEntity, HrvatskaStrijela.Database" />
</bag>
</class>
</hibernate-mapping>
Code:
public class CompetitorEntity
{
private int _competitorId;
private string _name;
private IList _results = new ArrayList();
public int CompetitorId
{
get { return _competitorId; }
set { _competitorId = value; }
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public IList Results
{
get { return _results; }
set { _results = value; }
}
public CompetitorEntity()
{}
}
tournament.hbm.xmlCode:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" namespace="HrvatskaStrijela.Database.Entities"
assembly="HrvatskaStrijela.Database">
<class name="HrvatskaStrijela.Database.Entities.TournamentEntity, HrvatskaStrijela.Database" table="TOURNAMENT">
<id name="TournamentId" column="TOURNAMENTID" type="Int32">
<generator class="native">
<param name="sequence">GEN_TURNIR_ID</param>
</generator>
</id>
<property name="Naziv" type="string" not-null="true" />
<bag name="Results" cascade="all" lazy="true" inverse="true">
<key column="TOURNAMENTID" />
<one-to-many class="HrvatskaStrijela.Database.Entities.ResultEntity, HrvatskaStrijela.Database" />
</bag>
</class>
</hibernate-mapping>
Code:
public class TournamentEntity
{
private int _tournamentId;
private string _name;
private IList _results = new ArrayList();
public int TournamentId
{
get { return _tournamentId; }
set { _tournamentId = value; }
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public IList Results
{
get { return _results; }
set { _results = value; }
}
public TournamentEntity()
{}
}
and lastly
result.hbm.xmlCode:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" namespace="HrvatskaStrijela.Database.Entities"
assembly="HrvatskaStrijela.Database">
<class name="HrvatskaStrijela.Database.Entities.ResultEntity, HrvatskaStrijela.Database" table="RESULT">
<composite-id name="ResultPk" class="HrvatskaStrijela.Database.Entities.ResultPkEntity, HrvatskaStrijela.Database">
<key-many-to-one name="Tournament" column="TOURNAMENTID" class="HrvatskaStrijela.Database.Entities.TournamentEntity, HrvatskaStrijela.Database" />
<key-many-to-one name="Competitor" column="COMPETITORID" class="HrvatskaStrijela.Database.Entities.CompetitorEntity, HrvatskaStrijela.Database" />
</composite-id>
<property name="Result" type="Int32" not-null="true" />
</class>
</hibernate-mapping>
Code:
public class ResultEntity
{
private ResultPkEntity _resultPk;
private int _result;
public int Result
{
get { return _result; }
set { _result = value; }
}
public ResultPkEntity ResultPk
{
get { return _resultPk; }
set { _resultPk = value; }
}
public ResultEntity()
{}
}
Code:
public class ResultPkEntity
{
private CompetitorEntity _competitor;
private TournamentEntity _tournament;
public CompetitorEntity Competitor
{
get { return _competitor; }
set { _competitor = value; }
}
public TournamentEntity Tournament
{
get { return _tournament; }
set { _tournament = value; }
}
public ResultPkEntity()
{}
public override bool Equals(object obj)
{
return base.Equals (obj);
}
public override int GetHashCode()
{
return base.GetHashCode ();
}
}
And the code I'm running is: (bare with me, please :lol:)
Code:
_session = _sessionFactory.OpenSession();
CompetitorEntity ne = _session.Get(typeof (CompetitorEntity), 325) as CompetitorEntity;
TournamentEntity te = _session.Get(typeof (TournamentEntity), 18) as TournamentEntity;
ResultEntity re = new ResultEntity();
re.ResultPk=new ResultPkEntity();
re.ResultPk.Competitor=ne;
re.ResultPk.Tournament=te;
re.Result=123412;
_session.Save(re);
_session.Flush();
_session.Close();
And now for the culmination! The code throws an exception at _session.Flush().
I traced the error to:
Persister\EntityPersister.cs: Insert (Persist an object)
which calls
Persister\EntityPersister.cs: Dehydrate
The for loop does whatever it does on the field "Result=123412", and then continues on to the id part,
calls NullSafeSet on ResultPkEntity,
which calls NullSafeGetValues on ResultPkEntity,
which calls GetPropertyValues on ResultPkEntity. There it correctly recognizes that there are 2 fields in the key and tries to get their values.
AND HERE IS THE PROBLEM!!
It only gets the competitor object while the tournament object is <undefined value>. It is like property getter isn't working! I doesen't even raise an PropertyAccessException in Property\BasicGetter.cs:Get.
I checked the RuntimePropertInfo and it looked ok!
Any ideas? Help!
P.S. A long post a? :)