These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: problem with mapping a subclass
PostPosted: Tue Jul 11, 2006 3:42 am 
Newbie

Joined: Tue Jul 11, 2006 3:26 am
Posts: 6
I want a subclass from a subclass, but this is not working. I have read all the posts with the word subclass in it, but could not find a solution. In several posts (“Multiple Inheritance Levels / SubClass” from Kerry and “Are two levels of subclasses possible?” from aarnott) it is said that multiple inheritance levels are possible, so I must be doing something wrong.

This is my mapping:

Code:
<class name="HRM_BL.Person, HRM_BL" table="tbl_Person">
   <id name="Id" type="Int32" column="Person_Id" access="field.pascalcase-underscore">
      <generator class="identity" />
   </id>
   <discriminator column="P_Employee" />
   <property name="FirstName" column="P_First_Name" type="String" />
<property name="LastName" column="P_Name" type="String" />
</class>

<subclass name="HRM_BL.Employee, HRM_BL"
extends="HRM_BL.Person, HRM_BL" discriminator-value="E" >   
<property name="GroupStartDate" column="P_Date_Group_Started" type="DateTime" />
</subclass>

<subclass name="HRM_BL.InsuredEmployee, HRM_BL"
    extends="HRM_BL.Employee, HRM_BL" discriminator-value="I">
   <property name="InsuranceStartDate" column="P_Insurance_Started" type="DateTime" />
<property name="InsuranceEndDate" column="P_Insurance_Ended" type="DateTime" />
</subclass>


This is ‘my’ error:

Code:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. -> Nhibernate.WrongClassException: Object with id: 1 was not of the specified subclass: HRM_BL.Employee (Discriminator: I)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 11, 2006 4:13 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Make sure NHibernate sees the mapping for InsuredEmployee. Try putting all of Person's subclasses inside its <class>, i.e.:
Code:
<class name="...Person...">
    ...
    <subclass name="Employee" ...>
    ...
        <subclass name="InsuredEmployee" ...>
        ...
        </subclass>
    </subclass>
</class>


Note that you won't need the extends attribute if you nest the mappings.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 11, 2006 4:53 am 
Newbie

Joined: Tue Jul 11, 2006 3:26 am
Posts: 6
Thanks for the suggestion. Tried it, but it produces the same error :-(

I have just noticed I did not say in my post when I get this error. Because the mapping is not entirely wrong. I can use the InsuredEmployee, but I cannot use the Employee. For example: I can get a list of InsuredEmployees, but I get the error when I want to get a list of Employees. Maybe this bit of extra information clarifies the situation.

Any other ideas?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 11, 2006 7:30 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Hmm, can you post your code? And also your class declarations, if possible.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 11, 2006 9:39 am 
Newbie

Joined: Tue Jul 11, 2006 3:26 am
Posts: 6
Ok, it quite a bit, but here it goes. I have left non-essential things out to keep the code a bit compact. I hope it will be enough. If you need something more, just ask me what.

The following code works for the InsuredEmployee, but not for the Employee. I hope you can figure out what I am doing wrong.

Mapping:

Code:
<class name=" HRM_BL.Person, HRM_BL" table="tbl_Person">
   <id name="Id" type="Int32" column="Person_Id" access="field.pascalcase-underscore">
      <generator class="identity" />
   </id>
   <discriminator column="P_Employee" />
   <property name="FirstName" column="P_First_Name" type="String" />
   <property name="LastName" column="P_Name" type="String" />
   <property name="BirthDate" column="P_Date_Birth" type="DateTime" />
   <property name="BirthPlace" column="P_Place_Birth" type="String" />
   <property name="BirthCountry" column="P_Birth_Country_Id" type="Int32" />
   <property name="Nationality" column="P_Nationality_Id" type="Int32" />
   <property name="Language" column="P_Language_Cd" type="String" />
   <property name="Gender" column="P_Gender" type="String"/>
   <subclass name=" HRM_BL.Employee, HRM_BL" discriminator-value="E" >
   <property name="GroupStartDate" column="P_Date_Group_Started" type="DateTime" />
   <property name="PensionDate" column="P_Pension_Date" type="DateTime" />
   <property name="PrePensionDate" column="P_PrePension_Date" type="DateTime" />
   <subclass name=" HRM_BL.InsuredEmployee, HRM_BL"  discriminator-value="I">
      <property name="InsuranceStartDate" column="P_Insurance_Start_Date" type="DateTime" />
      <property name="InsuranceEndDate" column="P_Insurance_End_Date" type="DateTime" />
   </subclass>
   </subclass>
</class>


Class declarations:

Code:
namespace HRM_BL
{   
  public class Person
  {
    private int _Id;
    private string _firstName;
    private string _lastName;
    private DateTime _birthDate;
    private string _birthPlace;
    private int _birthCountry;
    private int _nationality;
    private string _language;
    private string _gender;

    public string Gender
    {
      get { return _gender; }
      set { _gender = value; }
    }
   
    public string Language
    {
      get { return _language; }
      set { _language = value; }
    }
   

    public int Nationality
    {
      get { return _nationality; }
      set { _nationality = value; }
    }
   

    public int BirthCountry
    {
      get { return _birthCountry; }
      set { _birthCountry = value; }
    }
   

    public string BirthPlace
    {
      get { return _birthPlace; }
      set { _birthPlace = value; }
    }
   

    public DateTime BirthDate
    {
      get { return _birthDate; }
      set { _birthDate = value; }
    }
   

    public string LastName
    {
      get { return _lastName; }
      set { _lastName = value; }
    }
   

    public string FirstName
    {
      get { return _firstName; }
      set { _firstName = value; }
    }
   
    public int Id
    {
      get { return _Id; }
      set { _Id = value; }
    }
   
  }
}


Code:
namespace HRM_BL
{
  public class Employee : Person
  {
    private DateTime _groupStartDate;
    private DateTime _pensionDate;
    private DateTime _prePensionDate;

    public DateTime PrePensionDate
    {
      get { return _prePensionDate; }
      set { _prePensionDate = value; }
    }
   
           
    public DateTime PensionDate
    {
      get { return _pensionDate; }
      set { _pensionDate = value; }
    }
   

    public DateTime GroupStartDate
    {
      get { return _groupStartDate; }
      set { _groupStartDate = value; }
    }
   
  }
}


Code:
namespace HRM_BL
{
  public class InsuredEmployee : Employee
  {
   private DateTime _insuranceStartDate;
private DateTime _insuranceEndDate;

    public DateTime InsuranceStartDate
    {
      get { return _insuranceStartDate; }
      set { _insuranceStartDate = value; }
    }

    public DateTime InsuranceEndDate
    {
      get { return _insuranceEndDate; }
      set { _insuranceEndDate = value; }
    }

  }
}


The form where I load the data:

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using NHibernate.Cfg;
using NHibernate.Expression;
using NHibernate;
using System.Collections;
using Library_UI.Controls;
using Library_UI.TemplateForms;
using HRM_BL;

namespace HRM.Parameters
{
  public class EmployeeOverview : GeneralOverviewForm
  {
    #region Declarations

    private IDILabel lblDescription;
    private IDISearchBox txtDescription;
    private ColumnHeader columnHeader2;
    IList _list;
    ISession _session;
    private ColumnHeader columnHeader3;
    private IContainer components = null;
    public ListViewItem objEmployeeItem;

    #endregion

    public EmployeeOverview()
    {
      InitializeComponent();
      this.LoadData();
    }

    private void LoadData()
    {
      _session = NHibPersistor.SessionFactory.OpenSession();
      _list = _session.CreateCriteria(typeof(InsuredEmployee)).List();
      lvOverview.Items.Clear();

      foreach (InsuredEmployee employee in _list)
      {
        objEmployeeItem = lvOverview.Items.Add(employee.Id.ToString());
        objEmployeeItem.SubItems.Add(employee.LastName);
      }
      _session.Close();
    }
  }
}


the NHibpersistor:

Code:
using System;
using System.Collections.Generic;
using System.Text;
using NHibernate;
using NHibernate.Cfg;

namespace HRM_BL
{
  public static class NHibPersistor
  {
    private static Configuration _config;
    private static ISessionFactory _factory;

    public static ISessionFactory SessionFactory
    {
      get
      {
        if (_factory == null)
        {
          _config = new Configuration();
          _config.AddAssembly("HRM_BL");
          _factory = _config.BuildSessionFactory();
        }
        return _factory;
      }
    }
  }
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 12, 2006 6:41 am 
Newbie

Joined: Tue Jul 11, 2006 3:26 am
Posts: 6
Hey, to keep you informed of my tests:

I tried getting a list of Persons, but got the same error (but now for Person of course):
Code:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. -> Nhibernate.WrongClassException: Object with id: 1 was not of the specified subclass: HRM_BL.Person (Discriminator: I)


This is a bit weird since Person is not a subclass.

Then I have tried getting a list of Persons after changing the mapping-xml (left out the part about subclass InsuredEmployee), but still same error as above.

Last thing I tried was getting a list of Persons after changing all discriminator values on my DB to 'E' instead of 'I'. And still I get pretty much the same error.
Code:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. -> Nhibernate.WrongClassException: Object with id: 1 was not of the specified subclass: HRM_BL.Person (Discriminator: E)


In the last situation however it is no problem to get a list of Employees.

So it seems there is no problem getting data from the lowest level in the hierarchy (because there is no underlying subclass InsuredEmployee in this situation), but I cannot get data from higher levels.
Maybe I have to use different code to get data from higher levels? I hope you can help me.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 12, 2006 10:57 am 
Newbie

Joined: Tue Jul 11, 2006 3:26 am
Posts: 6
Problems solved.

First thing I have changed was adding a discriminator-value to the Person-class. I do not know if this is really necessary, but it is the logic thing to do when you think about it.

Second change was a problem of different types on the DB and in the code. The column used for the discriminator-value was defined as CHAR, but in the xml the discriminator-value was implicitly set as string. After explicitly changing the type of the discriminator value to Char, everything seems to be working.

I would like to thank the people who tried to find the solution. I hope to be able to help others when you have a problem.

Greetz


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.