Search code examples
c#asp.netnhibernatenhibernate-mappingunion-subclass

Object does not match target type.. Exception occured getter


I have a huge problem! I keep getting an exception when mapping an abstract class with multiple union-subclasses in nhibernate. When I use only one union-subclass I dont get any error and everything works fine. When I use more subclasses this error occures:

[TargetException: Object does not match target type.] System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target) +10909543 System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +115 System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +54 System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture) +61 System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index) +19 NHibernate.Properties.BasicGetter.Get(Object target) +99

[PropertyAccessException: Exception occurred getter of MedControlWeb.Models.Logs.Log.Code] NHibernate.Properties.BasicGetter.Get(Object target) +183 NHibernate.Engine.UnsavedValueFactory.GetUnsavedIdentifierValue(String unsavedValue, IGetter identifierGetter, IType identifierType, ConstructorInfo constructor) +160 NHibernate.Tuple.PropertyFactory.BuildIdentifierProperty(PersistentClass mappedEntity, IIdentifierGenerator generator) +200 NHibernate.Tuple.Entity.EntityMetamodel..ctor(PersistentClass persistentClass, ISessionFactoryImplementor sessionFactory) +775 NHibernate.Persister.Entity.AbstractEntityPersister..ctor(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) +835 NHibernate.Persister.Entity.UnionSubclassEntityPersister..ctor(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping) +220 NHibernate.Persister.PersisterFactory.CreateClassPersister(PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping cfg) +369 NHibernate.Impl.SessionFactoryImpl..ctor(Configuration cfg, IMapping mapping, Settings settings, EventListeners listeners) +2199 NHibernate.Cfg.Configuration.BuildSessionFactory() +181

My hbm file:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="MedControlWeb"
                   namespace="MedControlWeb.Models.Logs">

  <class name="Log" abstract="true" lazy="false">
    <id name="Code" column="code">
      <generator class="hilo"/>
    </id>

    <property name="Description" column="description"/>
    <property name="User" column="user"/>
    <property name="Timestamp" column="timestamp"/>
    <property name="Action" column="action"/>

    <union-subclass name="SettingsLog" table="settings_log" lazy="false">
    </union-subclass>

    <union-subclass name="JobLog" table="job_log" lazy="false">
    </union-subclass>

  </class>
</hibernate-mapping>

My abstract super class:

public class Log
{
    public int Code { get; set; }
    public DateTime Timestamp { get; set; }
    public MedControlWeb.Enums.Action Action { get; set; }
    public string Description { get; set; }
    public int User { get; set; }
}

One of the subclasses:

public class SettingsLog : Log
{        
}

Where am I going wrong?

Edit: What can I do to solve this error? I dont see how I can fix it since I have proper get methods?


Solution

  • Believe or not, solution here is really surprisingly simple. This is the mapping:

    <class name="Log" ...
        ...
        <union-subclass name="SettingsLog" table="settings_log" lazy="false">
        </union-subclass>
    
        <union-subclass name="JobLog" table="job_log" lazy="false">
        </union-subclass>
    

    This is above snippet of the class SettingsLog:

    public class SettingsLog : Log // this is it, SettingsLog is also a Log
    {...}
    

    which is working and for sure, the SettingsLog - is also Log. The issue reported, does not come from the fact:

    ... getting an exception when mapping an abstract class with multiple union-subclasses...

    But with a fact, that the other mapped union-subclass is not a Log:

    public class JobLog // this is NOT a Log..
    {...}
    

    That's why we can see:

    Exception: Object does not match target type
    (well - yes, because the JobLog is not Log)

    So, just assure that JobLog is subclass of Log... all will start to work

    public class JobLog : Log