0

A Teacher has a one-to-one with a Student.

A SpecialTeacher extends Teacher but deals specifically with SpecialStudents.

Using table per class in the hierarchies.


    public class Teacher
    {
        public virtual int Id { get; set; }
        public virtual int DepartmentId { get; set; }
        public virtual String Name { get; set; }
        public virtual Student Student { get; set; }
    }

    public class SpecialTeacher : Teacher
    {
        public virtual string TelephoneNumber { get; set; } //SpecialTeachers get to have a phone
        public virtual SpecialStudent SpecialStudent { get { return (SpecialStudent)base.Student; } set { Student = value; } }
    }

    public class Student
    {
        public virtual int Id { get; set; }
        public String Name { get; set; }
    }

    public class SpecialStudent : Student
    {
        public int SpecialMark { get; set; }
    }

and the associated mappings:

<class name="Student">
    <id name="Id" />
    <property name="Name" />
</class>

<joined-subclass name="SpecialStudent" extends="Student">
  <key column="Id" />
  <property name="SpecialMark" />
</joined-subclass>

<class name="Teacher">
  <id name="Id" />
  <property name="DepartmentId" />
  <property name="Name" />

  <many-to-one name="Student" column="StudentId" />
</class>

<joined-subclass name="SpecialTeacher" extends="Teacher">
  <key column="Id" />
  <property name="TelephoneNumber" />
</joined-subclass>

So, let's say that we want to get the average mark for SpecialStudents for a given department:

    public double GetAverageScoreForSpecialStudentsByDepartment(int departmentId)
    {
        return CurrentSession.Query<SpecialTeacher>()
            .Where(st => st.DepartmentId == departmentId)
            .Average(ss => ss.SpecialStudent.SpecialMark);
    }

The test will fail because it will complain that SpecialStudent is not a mapped property of SpecialTeacher.

The only way that I can think of avoiding this issue is to map the property, but this is duplication since the base Teacher is already mapped to the Student hierarchy.

Update

I meant to also mention that previously we had the SpecialTeacher set up like:

public class SpecialTeacher : Teacher
{
    public virtual string TelephoneNumber { get; set; } //SpecialTeachers get to have a phone
    public virtual new SpecialStudent Student { get { return (SpecialStudent)base.Student; } set { Student = value; } }
}

which did appear to work ok, but Envers did not work with it when retrieving audited data.

rae1
  • 6,066
  • 4
  • 27
  • 48
Rezler
  • 1,064
  • 1
  • 8
  • 21

1 Answers1

1

The only way that I can think of avoiding this issue is to map the property, but this is duplication since the base Teacher is already mapped to the Student hierarchy.

This is not duplication as you never mapped the SpecialStudent property in the SpecialTeacher mapping file. Although you correctly defined the relationship in code, NHibernate has no way of knowing a SpecialTeacher is suppose to have a SpecialStudent. The code is use by NHibernate to recreate the object from the tables, but only if you define the correct relationships in your mapping.

Remeber that BaseTeacher to BaseStudent does not imply SpecialTeacher to SpecialStudent relationship.

rae1
  • 6,066
  • 4
  • 27
  • 48
  • How would this be mapped then? I added a many-to-one to the SpecialTeacher mapping file: , but it complains that StudentId is an invalid column name. Presumably because it is trying to find it on the SpecialStudent table. I'm using a table per class, so it is not there. Is there any way to get it to reference the StudentId property in the BaseStudent or will I have to add a mapping to SpecialTeacher for that? Thanks. – Rezler Jan 16 '13 at 16:36
  • Where in your mapping do you define a `StudentId` column? I only see `Id`. – rae1 Jan 16 '13 at 21:19
  • The StudentId column is mapped through on Teacher. – Rezler Jan 17 '13 at 09:21
  • The StudentId column is on the Teacher table. – Rezler Jan 17 '13 at 15:15
  • Nevermind. However, the `StudentId` column needs to be defined in the `SpecialTeacher` mapping file as I don't believe NHibernate makes it inherit it from the base mapping. Take a look at [this](http://nhforge.org/doc/nh/en/index.html#inheritance-tablepersubclass-discriminator). – rae1 Jan 17 '13 at 15:26
  • I added the following to the SpecialTeacher mapping: , and then changed the SpecialStudent property on SpecialTeacher to be an auto property. Everything looks to be working fine so far. – Rezler Jan 17 '13 at 16:24