views:

621

answers:

3

Hi,

I am having a problem when trying create a many to many mapping. Consider the following tables:

CREATE TABLE [dbo].[student]
(
    [Id]            INT             IDENTITY (1, 1) NOT NULL,
    [Name]          NVARCHAR(255)   NOT NULL,
    -- Some other stuff...      
)

CREATE TABLE [dbo].[Subject]
(
    [Id]            INT             IDENTITY (1, 1) NOT NULL,
    [Name]  NVARCHAR (50)   NOT NULL,

    -- Some other stuff...
)

CREATE TABLE [dbo].[studentToSubject]
(
    [studentId] INT NOT NULL,
    [subjectId]     INT NOT NULL,
)

The interesting part of my student mapping file looks like this:

<id name="Id" type="Int32">
      <column name="Id" sql-type="int" not-null="true" unique="true"/>
      <generator class="native" />
    </id>

      <property name="Name" not-null="true" />
      <bag name="subjects" table="studentToSubject">
          <key column="studentId"></key>
          <many-to-many column="subjectId" class="subject" />
      </bag>

I want to end up with a student with a collection of their subjects. However, I get an error:

NHibernate.MappingException: Could not determine type for: MyApp.Domain.Subject, MyApp.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=865c2d2b185d0c4b, for columns: NHibernate.Mapping.Column(studentId).

I have seen some examples of this type of mapping, but they differ in the fact that their Id columns have name that match the mapping table name, for example their Id column in the student table is called 'studentId'. I cannot do this (it has to be Id) but I think this is the cause of the problem.

Thanks

A: 

It seems like you are either missing the mapping file for Subject (did you remember to include it properly?) or you need to provide the full path if it is in a different namespace.

ShaneC
A: 

Did you remember to set the .hbm.xml mapping files to an Embedded Resource? Also this line is not correct.

<many-to-many column="subjectId" class="subject" />

Subject should be capital S and it is good practice to give the namespace and assembly. such as <many-to-many column="subjectId" class="MyApp.Domain.Subject, MyApp.Domain" />

Adam
A: 

Please correct me if I'm wrong, but I guess there's something messy about your Id mapping. Perhaps it can be done the way you do and I have never seen it, this is possible.

Though I would write my mapping like so:

<class name="Student"> <!-- I omit the table attribute as both your class and table seems to have the same name. -->
  <id name="Id">
    <generator class="native"/> <!-- Though I would recommend using "identity" if SQL Server's used. -->
  </id>

  <property name="Name" length="255" not-null="true"/>

  <list name="Subjects" not-null="true" table="StudentToSubject">
    <key column="studentId" />
    <many-to-many column="studentId" class="Subject" />
  </list>
</class>

Within the element, it is optional to specify the not-null, unique, type and sql-type attributes as NHibernate will determine them during runtime using reflection, though I understand that for pedagogy purposes, it is better to write those. Plus, if you want your Id property name within your object class be the same as your table field, you may just omit the column attribute. NH will then consider using the same name as the property for the data table field Id field.

As for your collection of subjects, if you intend to use a Dictionary in your Sudent class, you'd better the element instead of . However, if you want a List, you'd better opt for the element as I did. This all depends on your needs and your objective through this exercise.

Please, consider that I took this NH XML mapping right from the top of my head, and I didn't test it, so it might contain errors on fly.

In addition to this, you can take an eye out on this: Chapter 6. Collection Mapping

Hope this helps! =)

Will Marcouiller