NHibernate en Inheritance

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Ik heb een probleem met NHibernate in combinatie met Inheritance. Ik zal eerst kort de situatie beschrijven.

Situatie
Plaatjes zeggen meer dan woorden ;)
Afbeeldingslocatie: http://home.planet.nl/~lyckl022/temp/person_uml.png

Ik maak gebruik van het "Table Per Subclass" mechanisme.

Okay, het probleem is als volgt. Wanneer iemand een Teacher EN Student is krijg ik de onderstaande melding:

code:
1
Object with id: 2 was not of the specified subclass: Teacher (loading object was of wrong class [Student])


Dit krijg ik als ik gewoon List<Person>() aanroep. Op één of andere manier probeert NHibernate er al een ander type van te maken. Het rare is, als ik alle teacher's opvraag dan verschijnt deze melding niet en krijg ik alle teacher's te zien. Als ik alle Students opvraag dan komt de fout wel naar boven.

Ik heb al geprobeerd om de query aan te passen maar dit werkt ook niet. Ik krijg dan helemaal geen resultaten meer terug :o

code:
1
from Person p where p.class = Person


Ik kwam op de onderstaande site uit maar ik hoop niet dat dit waar is:
down vote


I fell in this same error today (for the second time actually) and I finally realized what's the issue here.

I don't know about others ORM but using nHibernate you can't share an Id over two different classes (subclasses). That's not the way inheritance is supposed to be in nHibernate. Table-per-class hierarchy is meant to have separate tables to specify a parent table (in your issue you are trying the opposite).

All this actually make sense since to access Client or Employee you actually refer to the Person Id (at first I didn't paid attention to this but now is totally clear).

The solution is to refactor the domain model and change the relationship between you classes from as "is-a" to a "has-a" relationship and expose common properties (if needed) via an interface.
Ik heb mijn probleem al aangekaart op het NHibernate forum zelf, maar ik krijg daar maar geen reactie. Ik hoop dat één van jullie mij verder kan helpen.

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
Zelf NHibernate nooit gebruikt maar wat ik begrijp is dat je Teacher en Student laat extenden van Person. Dit kan niet, want je kan maar van 1 class extenden (in de meeste talen dan).

Zoals de post die je quote zelf al zegt: je moet overstappen naar een model waarbij een Person Teacher eigenschappen en Student eigenschappen heeft. Een persoon zal ook nooit een teacher "zijn", maar een beroep "hebben".

Acties:
  • 0 Henk 'm!

  • alwinuzz
  • Registratie: April 2008
  • Laatst online: 05-09 09:24
Stel je gebruikte geen NH, hoe zou je dan een object maken dat zowel Teacher als Student is? Niet door te subclassen van Teacher én Student, want dat kan niet in C#.

Wat ReenL en StackOverflow al zeggen:
The solution is to refactor the domain model and change the relationship between you classes from as "is-a" to a "has-a" relationship and expose common properties (if needed) via an interface.
Edit: kan je hiermee verder? Niet iedereen weet wat hiermee bedoeld wordt denk ik.

[ Voor 9% gewijzigd door alwinuzz op 20-04-2011 23:27 ]


Acties:
  • 0 Henk 'm!

  • HMS
  • Registratie: Januari 2004
  • Laatst online: 21-08 23:06

HMS

Dubbele overerving van classes kan niet in C#. Dus een object kan niet een Teacher en een Student zijn, logisch dus dat NHibernate gaat zeuren. (tenzij je er natuurlijk een derde klasse tussen propt om het toch werkend te krijgen, maar dan moet er al een belletje gaan rinkelen dat je design niet helemaal klopt.)

Acties:
  • 0 Henk 'm!

  • Spiral
  • Registratie: December 2005
  • Niet online
Een oplossing kan zijn:

XML:
1
2
  <joined-subclass name="Teacher" table="Teacher" extends="Person">
    <key column="PersonID" />


Waarbij je Person óók een C# klasse is en deze heeft ook een hbm.xml file

XML:
1
2
3
4
  <class name="Person" table="Person">
    <id name="ID" column="ID">
      <generator class="native" />
    </id>

To say of what is that it is not, or of what is not that it is, is false, while to say of what is that it is, and of what is not that it is not, is true. | Aristoteles


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Thanks heren, het begint nu pas te dagen dat ik multiple inheritance wil gebruiken... In C# lukt dat idd niet en logisch dat NHibernate dat ook niet kan :F

Ik kan er wel "has-a" van maken alleen qua benadering van properties krijg je dan wel uglyness.

Afbeeldingslocatie: http://home.planet.nl/~lyckl022/temp/person_uml2.png

C#:
1
2
Student student = new Student();
student.Person.FirstName = "Test";


Ik kan alles wel op een hoger niveau doorlinken maar dat is een partij werk en tevens foutgevoelig. Dan zou ik er een interface tussen moeten zetten IPerson of iets dergelijks. Maar dan moet je nog steeds handmatig de waardes doorlinken.

C#:
1
2
3
4
5
6
7
public class Teacher : IPerson {
   public virtual Person Person;

   public string FirstName {
      return person.FirstName;
   }
}


Ik vraag me trouwens af of ik een nieuwe identifier moet gaan gebruiken per table (Student of Teacher) of dat ik de Person's ID gewoon kan gebruiken. Maar hier kom ik wel snel genoeg achter :)

Denk jullie dat het bovenstaande diagram moet gaan werken (nog even los gezien van een eventuele IPerson interface)?

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ik zou de has-a juist andersom leggen. Een Persoon heeft 0 of meerdere Rollen/Functies. Dus een Persoon bevat de naam/adres/geboortedatum/etc, en de Persoon heeft dan 2 rollen. De rol Student, en de rol Teacher.

Een Teacher/Student is dan dus geen Person, maar een Rol/Functie van een Person

[ Voor 16% gewijzigd door Woy op 21-04-2011 10:53 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Woy schreef op donderdag 21 april 2011 @ 10:52:
Ik zou de has-a juist andersom leggen. Een Persoon heeft 0 of meerdere Rollen/Functies. Dus een Persoon bevat de naam/adres/geboortedatum/etc, en de Persoon heeft dan 2 rollen. De rol Student, en de rol Teacher.

Een Teacher/Student is dan dus geen Person, maar een Rol/Functie van een Person
Verhip, zo had ik er nog niet over nagedacht! Lijkt me ook beter om mee te werken programmeer-technisch gezien.

PSN: Norfirin

Pagina: 1