Arnon Axelrod
Arnon Axelrod

Reputation: 1

"Error executing multi criteria" exception when using subclasses in NHibernate

I'm trying to map the following classes to the following tables using NH:

public abstract class Person
{
    public string SSN { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Customer : Person
{
    public string ClubMemberId { get; set; }
    //...
}

public class Employee : Person
{
    public string Department { get; set; }
    public int BankAccountNumber { get; set; }
    public int BankId { get; set; }
}

public class Cashier : Employee
{
    // no additional properties here (only methods)
}

Tables:

Persons:
  SSN (Primary Key)
  FirstName
  LastName
  PersonType  (discriminator: values can be Customer, Employee or Cashier)
  ClubMemberId

Employees:
  PersonSSN (Primary key and foriegn key to Persons.SSN
  Department
  BankAccountNumber
  BankId

Here's the hbm I tried to use for that:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
               namespace="BusinessLogic"
               assembly="BusinessLogic"
               default-access="property"
               default-lazy="false">

<class name="Person" table="Persons" discriminator-value="None">
  <id name="SSN" />
  <discriminator column="PersonType" />
  <property name="FirstName" />
  <property name="LastName" />

  <subclass name="Customer" discriminator-value="Customer">
    <property name="ClubMemberId" />
  </subclass>

  <subclass name="Employee" discriminator-value="Employee" >
    <join table="Employees">
      <key column="PersonSSN" />
      <property name="EmployeeId" />
      <property name="BankAccountNumber" />
      <property name="BankId" />
    </join>
  </subclass>

  <subclass name="Cashier" discriminator-value="Cashier" extends="Employee" />
    <!--<join table="Employees">
      <key column="PersonSSN" />
      <property name="CashierDummyProperty" />
    </join>
  </subclass>-->
</class>

</hibernate-mapping>

When I try to load all the Employee records (Employee and Cashier) using the following code:

private ObservableCollection<T> LoadCollection<T>()
   where T : class
{
    var records = _session.QueryOver<T>().Future();
    return new ObservableCollection<T>(records);
}

(where T is Employee), I get the following exception:

NHibernate.HibernateException: Error executing multi criteria : [SELECT this_.SSN as SSN1_0_, this_.FirstName as FirstName1_0_, this_.LastName as LastName1_0_, this_1_.EmployeeId as EmployeeId2_0_, this_1_.BankAccountNumber as BankAcco3_2_0_, this_1_.BankId as BankId2_0_ FROM Persons this_ inner join Employees this_1_ on this_.SSN=this_1_.PersonSSN WHERE this_.PersonType='Employee';
SELECT this_.SSN as SSN1_0_, this_.FirstName as FirstName1_0_, this_.LastName as LastName1_0_ FROM Persons this_ WHERE this_.PersonType='Cashier';
] ---> System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
at System.ThrowHelper.ThrowArgumentOutOfRangeException()
at System.Collections.Generic.List`1.get_Item(Int32 index)
at NHibernate.Impl.MultiCriteriaImpl.GetResultsFromDatabase(IList results) in d:\\CSharp\\NH\\nhibernate\\src\\NHibernate\\Impl\\MultiCriteriaImpl.cs:line 220
--- End of inner exception stack trace ---
at NHibernate.Impl.MultiCriteriaImpl.GetResultsFromDatabase(IList results) in d:\\CSharp\\NH\\nhibernate\\src\\NHibernate\\Impl\\MultiCriteriaImpl.cs:line 259
at NHibernate.Impl.MultiCriteriaImpl.DoList() in d:\\CSharp\\NH\\nhibernate\\src\\NHibernate\\Impl\\MultiCriteriaImpl.cs:line 171
at NHibernate.Impl.MultiCriteriaImpl.ListIgnoreQueryCache() in d:\\CSharp\\NH\\nhibernate\\src\\NHibernate\\Impl\\MultiCriteriaImpl.cs:line 143
at NHibernate.Impl.MultiCriteriaImpl.List() in d:\\CSharp\\NH\\nhibernate\\src\\NHibernate\\Impl\\MultiCriteriaImpl.cs:line 91
at NHibernate.Impl.FutureCriteriaBatch.GetResultsFrom(IMultiCriteria multiApproach) in d:\\CSharp\\NH\\nhibernate\\src\\NHibernate\\Impl\\FutureCriteriaBatch.cs:line 24
at NHibernate.Impl.FutureBatch`2.GetResults() in d:\\CSharp\\NH\\nhibernate\\src\\NHibernate\\Impl\\FutureBatch.cs:line 73
at NHibernate.Impl.FutureBatch`2.get_Results() in d:\\CSharp\\NH\\nhibernate\\src\\NHibernate\\Impl\\FutureBatch.cs:line 29
at NHibernate.Impl.FutureBatch`2.GetCurrentResult[TResult](Int32 currentIndex) in d:\\CSharp\\NH\\nhibernate\\src\\NHibernate\\Impl\\FutureBatch.cs:line 79
at NHibernate.Impl.FutureBatch`2.<>c__DisplayClass4`1.<GetEnumerator>b__3() in d:\\CSharp\\NH\\nhibernate\\src\\NHibernate\\Impl\\FutureBatch.cs:line 63
at NHibernate.Impl.DelayedEnumerator`1.<get_Enumerable>d__0.MoveNext() in d:\\CSharp\\NH\\nhibernate\\src\\NHibernate\\Impl\\DelayedEnumerator.cs:line 26
at System.Collections.ObjectModel.ObservableCollection`1.CopyFrom(IEnumerable`1 collection)
at System.Collections.ObjectModel.ObservableCollection`1..ctor(IEnumerable`1 collection)
at BusinessLogic.DataProvider.LoadCollection[T]() in C:\\Users\\Arnon\\Documents\\Visual Studio 2008\\Projects\\NHibernateDemo\\BusinessLogic\\DataProvider.cs:line 58
at BusinessLogic.DataProvider..ctor() in C:\\Users\\Arnon\\Documents\\Visual Studio 2008\\Projects\\NHibernateDemo\\BusinessLogic\\DataProvider.cs:line 28

Other findings I had:

  1. If I add a new property to the Cashier class, NH looks for the corresponding field in Persons and not in Employees (I added it to Employees where I'd expected it to be).

  2. If I explicitly specificy the same join of the Employees table inside the Cashier sub-class element (in order to add the additional property), I get the same exception mentioned above.

What am I doing wrong here?

PS: IMHO, even if I'm doing something wrong here, NH should provide a more descriptive exception here.

Upvotes: 0

Views: 1033

Answers (1)

Gerke Geurts
Gerke Geurts

Reputation: 632

This is a bug in the NHibernate MultiQueryImpl code (see https://nhibernate.jira.com/browse/NH-2959). It does not handle polymorphic queries successfully.

Upvotes: 0

Related Questions