Search code examples
c#.netnhibernatenhibernate-mapping

NHibernate.MappingException: NHibernate.PropertyNotFoundException: Could not find a getter for property in class


Having trouble with nHibernate mapping my enum to the DB.

Tried looking at the mapping but can't see anything wrong, my suspicions by this point are that it may have something to do with the enum?

Here's Fortron.Crm.Domain.Policy:

namespace Fortron.Crm.Domain
{
   [Serializable]
   public class Policy
   {
      private PolicyStatus _policyStatus;

      public PolicyStatus PolicyStatus
      {
          get { return _policyStatus; }
          set { _policyStatus = value; }
      }
   }

Here's the class mapping

  <class name="Fortron.Crm.Domain.Policy, Fortron.Crm.Domain" table="Policy" lazy="false">
    <id name="Id" access="nosetter.camelcase-underscore" column="PolicyId" unsaved-value="-1">
      <generator class="identity" />
    </id>
    <set name="Claims" access="field.camelcase-underscore" inverse="true" lazy="false" cascade="save-update">
      <key column="PolicyId" />
      <one-to-many class="Fortron.Crm.Domain.Claim, Fortron.Crm.Domain" />
    </set>
    <many-to-one name="Product" column="ProductId" access="nosetter.camelcase-underscore" />
    <property name="PolicyNumber" />
    <property name="VehicleRegistrationNumber" />
    <property name="ContractNumber" />
    <property name="ContractPaymentAuthorised" />
    <property name="ContractPaymentAuthorisedAt" />
    <component name="Contact" access="nosetter.camelcase-underscore">
      <property name="Title" />
      <property name="GivenNames" />
      <property name="Surname" />
      <property name="BusinessName" />
      <property name="DateOfBirth" />
      <property name="Gender" column="GenderId" />
      <property name="TelephoneNumber" />
      <property name="MobileTelephoneNumber" />
      <property name="WorkTelephoneNumber" />
      <component name="Address" access="nosetter.camelcase-underscore">
        <property name="StreetLine1" column="StreetLine1" />
        <property name="StreetLine2" column="StreetLine2" />
        <property name="CityTown" column="CityTown" />
        <property name="Postcode" column="Postcode" />
        <many-to-one name="StateTerritory" column="StateTerritoryId" />
      </component>
    </component>
    <property name="CustomerNumber" column="CustomerNumber" not-null="false" />
    <property name="Vin" column="Vin" not-null="false"  />
    <property name="PolicyStatus" column="PolicyStatusId" />
  </class>

Lastly here's the stack trace:

Service cannot be started. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> NHibernate.MappingException: Could not compile the mapping document: Fortron.Crm.Domain.Policy.hbm.xml ---> NHibernate.MappingException: Problem trying to set property type by reflection ---> NHibernate.MappingException: class Fortron.Crm.Domain.Policy, Fortron.Crm.Domain, Version=2.0.0.1, Culture=neutral, PublicKeyToken=6f168f2566a816b4 not found while looking for property: PolicyStatus ---> NHibernate.PropertyNotFoundException: Could not find a getter for property 'PolicyStatus' in class 'Fortron.Crm.Domain.Policy'
   at NHibernate.Properties.BasicPropertyAccessor.GetGetter(Type type, String propertyName)
   at NHibernate.Util.ReflectHelper.ReflectedPropertyClass(String className, String name, String accessorName)
   --- End of inner exception stack trace ---
   at NHibernate.Util.ReflectHelper.ReflectedPropertyClass(String className, String name, String accessorName)
   at NHibernate.Mapping....

Any ideas?


Solution

  • Change your member signature to make it virtual:

    public virtual PolicyStatus PolicyStatus
    

    NHibernate expects all the members of your entity to be virtual for binding. This is necessary because NHibernate creates proxy (to implement lazy loading) in certain cases. Without marked as virtual, this will not be possible for NHibernate.

    You may refer this (or archive) article:

    The quick answer to that question is: because we need members to be virtual in order to do our lazy loading magic/voodoo.

    The longer answer is more interesting though. An important feature that any real ORM must have is transparent Lazy Loading. If you retrieve an object through an ORM, you don't want it to automatically pull in an entire object graph (not by default anyway), yet you don't want to litter your code with checks to see if certain associations have been loaded yet, and then loading them if necessary. This is the ORM's responsibility. Ideally, you want to be able to access properties and have the ORM load the necessary data upon first access of those properties if the data hasn't been retrieved yet.

    NHibernate has this ability, yet it doesn't require you to inherit from some kind of NHibernate base class or implement any interfaces or anything like that. So how does it work? Well, NHibernate uses proxies of your classes at runtime whenever lazy loading is required. Ok, so what exactly is a proxy? In this case, an NHibernate proxy is a type which is generated dynamically when NHibernate is initialized for your application (this only happens once upon application startup). A proxy type will be generated for each of your entities that hasn't explicitly been mapped to avoid lazy loading (more on this later). A proxy type for one of your entities will actually inherit from your entity, and will then intercept each possible call you can perform on that type.