I'm currently having a problem with NHibernate 1.2.1
.4000, when using lists.
I'm using it with C# and MySQL 5.0
Here the (simplified) context :
3 tables:
- project
- resource
- employee
Each project has several resources, and each resource is represented by an employee.
So here are my (simplified) SQL queries :
Code:
-- table `employee`
CREATE TABLE `employee` (
`emp_id` int(5) unsigned NOT NULL auto_increment,
`ldap` varchar(7) default NULL,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`emp_id`),
UNIQUE KEY `ldap_unique` (`ldap`)
) TYPE=InnoDB AUTO_INCREMENT=1 ;
-- table `project`
CREATE TABLE `project` (
`prj_id` int(4) unsigned NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`prj_id`),
) TYPE=InnoDB AUTO_INCREMENT=1 ;
-- table `resource`
CREATE TABLE `resource` (
`res_id` int(10) unsigned NOT NULL,
`prj_id` int(4) unsigned NOT NULL,
`pos` int(2) unsigned NOT NULL,
`emp_id` int(5) unsigned NOT NULL,
`role` varchar(50) default NULL,
PRIMARY KEY (`res_id`),
UNIQUE KEY `emp_unique_in_project` (`prj_id`,`emp_id`),
UNIQUE KEY `res_prj_unique` (`prj_id`,`pos`),
KEY `res_prj_fk` (`prj_id`),
KEY `res_emp_fk` (`emp_id`)
) TYPE=InnoDB;
--
-- Constraints
--
ALTER TABLE `resource`
ADD CONSTRAINT `resource_ibfk_1` FOREIGN KEY (`prj_id`) REFERENCES `project` (`prj_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
ADD CONSTRAINT `resource_ibfk_2` FOREIGN KEY (`emp_id`) REFERENCES `employee` (`emp_id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
I'd like to create a
Project class that contains a List of Resources.
An
Employee class that contains a List of Resources (not necessary).
A
Resource class that contains a Project property (or at least a property containing the project id) and an Employee property (or at least a property containing the employee id).
I think NHibernate is able to build the objects, if it has correct mapping files.
I've written these files :
Project.hbm.xmlCode:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="BIP.DatabaseAPI" assembly="BIP">
<class name="Project" table="project">
<id name="Id">
<column name="prj_id" sql-type="int" length="10" not-null="true"/>
<generator class="increment" />
</id>
<property name="Name" />
<list name="Resources" table="resource">
<key column="prj_id" foreign-key="res_prj_fk" />
<index column="pos" />
<one-to-many class="Resource" />
</list>
</class>
</hibernate-mapping>
Employee.hbm.xmlCode:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="BIP.DatabaseAPI" assembly="BIP">
<class name="Employee" table="employee">
<id name="Id">
<column name="emp_id" sql-type="int" length="5" not-null="true"/>
<generator class="increment" />
</id>
<property name="Name" />
<list name="Resources" table="resource">
<key column="emp_id" foreign-key="res_emp_fk" />
<index column="pos" />
<one-to-many class="Resource" />
</list>
</class>
</hibernate-mapping>
Resource.hbm.xmlCode:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="BIP.DatabaseAPI" assembly="BIP">
<class name="Resource" table="resource" lazy="false">
<id name="Id">
<column name="res_id" length="10" not-null="true" />
<generator class="increment" />
</id>
<property name="Project">
<column name="prj_id" />
</property>
<property name="Employee">
<column name="emp_id" />
</property>
<property name="Function">
<column name="role" length="50"/>
</property>
</class>
</hibernate-mapping>
Here are my classes :
Code:
namespace BIP.DatabaseAPI {
public class Project {
private Int32 id;
public virtual Int32 Id {
get { return this.id; }
set { this.id = value; }
}
private String name;
public virtual String Name {
get { return this.name; }
set { this.name = value; }
}
private IList<Resource> resources;
public virtual IList<Resource> Resources {
get { return this.resources; }
set { this.resources = value; }
}
public Project() {
this.resources = new List<Resource>();
}
public Project(String otp)
{
this.otp = otp;
this.type = 1;
this.decisionStatus = 1;
this.originalContractLevel = 1;
this.originalContractState = 's';
this.resources = new List<Resource>();
}
public Project(Int32 id, String otp) {
this.id = id;
this.otp = otp;
this.type = 1;
this.decisionStatus = 1;
this.originalContractLevel = 1;
this.originalContractState = 's';
this.resources = new List<Resource>();
}
public override bool Equals(object obj) {
return base.Equals(obj);
}
public override int GetHashCode() {
return base.GetHashCode();
}
}
}
Code:
namespace BIP.DatabaseAPI {
public class Resource {
private Int32 id;
public Int32 Id {
get { return this.id; }
set { this.id = value; }
}
private int pos;
public virtual int Pos {
get { return this.pos; }
set { this.pos = value; }
}
private Int32 employee;
public virtual Int32 Employee {
get { return this.employee; }
set { this.employee = value; }
}
private Int32 project;
public virtual Int32 Project {
get { return this.project; }
set { this.project = value; }
}
private String function;
public virtual String Function {
get { return this.function; }
set { this.function = value; }
}
public Resource() { }
public override bool Equals(object obj) {
return base.Equals(obj);
}
public override int GetHashCode() {
return base.GetHashCode();
}
}
}
And the long-awaited (Mapping)Exception:
Code:
L'exception NHibernate.MappingException n'a pas été gérée
Message="Unknown entity class: NHibernate.Collection.Generic.PersistentGenericList`1[[BIP.DatabaseAPI.Resource, BIP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"
Source="NHibernate"
StackTrace:
à NHibernate.Impl.SessionFactoryImpl.GetEntityPersister(Type theClass)
à NHibernate.Impl.SessionImpl.GetClassPersister(Type theClass)
à NHibernate.Impl.SessionImpl.GetEntityPersister(Object obj)
à NHibernate.Impl.SessionImpl.SaveWithGeneratedIdentifier(Object obj, CascadingAction action, Object anything)
à NHibernate.Impl.SessionImpl.Save(Object obj)
à BIP.DatabaseAPI.Manager.exec(String action, Object o) dans D:\workspace\BIP-SVN\trunk\src\BIP\DatabaseAPI\Manager.cs:ligne 103
à BIP.Indicators.ProjectIndicators.save(Manager mng, ListIndicator indicators) dans D:\workspace\BIP-SVN\trunk\src\BIP\Indicators\ProjectIndicators.cs:ligne 151
à BIP.Indicators.ProjectIndicators.save(Manager mng, ListIndicator indicators) dans D:\workspace\BIP-SVN\trunk\src\BIP\Indicators\ProjectIndicators.cs:ligne 133
à BIP.Indicators.ProjectIndicators.save(Manager mng, ListIndicator indicators) dans D:\workspace\BIP-SVN\trunk\src\BIP\Indicators\ProjectIndicators.cs:ligne 133
à BIP.Indicators.ProjectIndicators.save(Manager mng, ListIndicator indicators) dans D:\workspace\BIP-SVN\trunk\src\BIP\Indicators\ProjectIndicators.cs:ligne 133
à BIP.Indicators.ProjectIndicators.save() dans D:\workspace\BIP-SVN\trunk\src\BIP\Indicators\ProjectIndicators.cs:ligne 92
à BIP.Indicators.ProjectIndicators.Main() dans D:\workspace\BIP-SVN\trunk\src\BIP\Indicators\ProjectIndicators.cs:ligne 288
à System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
à System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
à Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
à System.Threading.ThreadHelper.ThreadStart_Context(Object state)
à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
à System.Threading.ThreadHelper.ThreadStart()
InnerException:
* first line means "The exception NHibernate.MappingException was not handled"
* "à" means "at"
This happens when I try to save my Project object.
It seems like the List<Resource> object is unknown to NHibernate.
If anyone has any idea, this will be really, really appreciated.
Because I've been stuck on this for one week, now, and I really can't spend more time on this. And I'm almost sure this is a stupid mistake...
If there are informations missing, just ask, I'll post them here!
Thank you in advance !