views:

82

answers:

1

I'm new to NHibernate, and am trying to map a domain model that has a bit of inheritence etc (see this question for full details on my model, starting a new question as this is a different error)

My base class has some abstract methods that each class beneath has to implement. This appears to be causing problems with NHibernate, even though I've implemented the class in my domain model, NHibernates proxy class seems to be having trouble.

One such method is SetRequired which is a void in my Question class and I've overriden it everywhere, but when I'm trying to test my mappings I'm getting this error:

PmqccFormIntegrationTests.TestJobVelocityQuestionPersists : FailedNHibernate.HibernateException : Creating a proxy instance failed
  ----> System.TypeLoadException : Method 'SetRequired' in type 'QuestionProxy' from assembly 'QuestionProxyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
at NHibernate.ByteCode.LinFu.ProxyFactory.GetProxy(Object id, ISessionImplementor session)
at NHibernate.Tuple.Entity.AbstractEntityTuplizer.CreateProxy(Object id, ISessionImplementor session)
at NHibernate.Persister.Entity.AbstractEntityPersister.CreateProxy(Object id, ISessionImplementor session)
at NHibernate.Event.Default.DefaultLoadEventListener.CreateProxyIfNecessary(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options, IPersistenceContext persistenceContext)
at NHibernate.Event.Default.DefaultLoadEventListener.ProxyOrLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
at NHibernate.Event.Default.DefaultLoadEventListener.OnLoad(LoadEvent event, LoadType loadType)
at NHibernate.Impl.SessionImpl.FireLoad(LoadEvent event, LoadType loadType)
at NHibernate.Impl.SessionImpl.Load(String entityName, Object id)
at NHibernate.Impl.SessionImpl.Load(Type entityClass, Object id)
at PmqccDomain.DataAccess.NHibernate.AbstractNHibernateDao`2.GetById(IdT id, Boolean shouldLock) in AbstractNHibernateDao.cs: line 31
at PMQCC_IntegrationTests.PmqccFormIntegrationTests.TestJobVelocityQuestionPersists() in PmqccFormIntegrationTests.cs: line 92
--TypeLoadException
at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type)
at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
at System.Reflection.Emit.TypeBuilder.CreateType()
at LinFu.DynamicProxy.ProxyFactory.CreateUncachedProxyType(Type[] baseInterfaces, Type baseType)
at LinFu.DynamicProxy.ProxyFactory.CreateProxyType(Type baseType, Type[] baseInterfaces)
at LinFu.DynamicProxy.ProxyFactory.CreateProxy(Type instanceType, IInterceptor interceptor, Type[] baseInterfaces)
at NHibernate.ByteCode.LinFu.ProxyFactory.GetProxy(Object id, ISessionImplementor session) 

I've tried setting 'abstract="true"' in my mapping files, and lazy="false" but I'm still getting the error. Thoughts?

EDIT: here is my current mapping

 <class name ="PmqccDomain.DomainObjects.Question,PmqccDomain" abstract="true" table="Questions">
    <id column="QuestionId" name="Id" type="Int32" unsaved-value="-1">
      <generator class="native"></generator>
    </id>
    <discriminator column="QuestionType" type="String" />
    <property name="Explanation"/>
    <many-to-one name="PmqccForm" class="PmqccDomain.DomainObjects.PmqccForm" column="PmqccFormId" />


    <!-- Subclass for Normal Question-->
    <subclass name="PmqccDomain.DomainObjects.NormalQuestion,PmqccDomain" abstract="true"  lazy="false">
      <property name="InputtedAnswer"/>

      <!-- Each Question Subclassed-->
      <subclass name="PmqccDomain.DomainObjects.AsConsQuestion,PmqccDomain" lazy="false" />
      <subclass name="PmqccDomain.DomainObjects.PiAlertQuestion,PmqccDomain" lazy="false">

        <many-to-one name="ResponsibleStaffMember" class="PmqccDomain.DomainObjects.StaffMember" column="ResponsibleStaffId" />

      </subclass>

    </subclass>

    <!-- Subclass for Job Velocity Question-->
    <subclass name="PmqccDomain.DomainObjects.JobVelocityQuestion,PmqccDomain" lazy="false">
      <property name="InputtedAnswer"/>

    </subclass>

  </class>
+1  A: 

I believe the key is to declare such methods as: protected internal abstract as this will allow the proxies to inherit from them. You read read more about this here.

DanP
thanks, this led me to my solution. I had it as protected internal abstract, but the problem is that as its internal, the DynamicProxy dll cannot access it. I made it public abstract and it works fine. It also shoudl work if you use the InternalsVisibleTo and set it to the dynamicProxy.dll
RodH257
@RodH257 - ah yes, I remembered facing a similar problem awhile back, but obviously got the specifics wrong - the posting I linked to helped me to solve the problem as well.
DanP