Search code examples
nhibernateormunion-subclass

How to map an abstract property with NHibernate union subclass?


Referring to Ayende's post here: http://ayende.com/blog/3941/nhibernate-mapping-inheritance

I have a similar situation that can be reached by extending the union-subclass mapping of the above post a bit, by adding an abstract Name-property to the Party. The model would be as follows:

public abstract class Party
{
    public abstract string Name { get; }
}

public class Person : Party
{
    public override string Name { get { return this.FirstName + " " + this.LastName; } }

    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
}

public class Company : Party
{
    public override string Name { get { return this.CompanyName; } }
    public virtual string CompanyName { get; set; }
}

I'm looking for a mapping that would allow me to query over the parties in the following manner:

session.QueryOver<Party>().Where(p => p.Name.IsLike("firstname lastname")).List();

The mapping I'm using:

<class name="Party" table="`party`" abstract="true">
<id access="backfield" name="Id">
  <column name="Id" />
  <generator class="sequence">
    <param name="sequence">party_id_seq</param>
  </generator>
</id>
<union-subclass name="Person" table="`person`">
  <property name="Name" formula="first_name || ' ' || last_name" update="false" insert="false" access="readonly">
  </property>
  <property name="FirstName">
    <column name="first_name" />
  </property>
  <property name="LastName">
    <column name="last_name" />
  </property>
</union-subclass>
<union-subclass name="Company" table="`company`">
  <property name="Name" access="readonly" update="false" insert="false">
    <column name="company_name" />
  </property> 
  <property name="CompanyName">
    <column name="company_name" />
  </property>
</union-subclass>

For both

session.QueryOver<Person>().Where(p => p.Name.IsLike("firstname lastname")).List();

and

session.QueryOver<Company>().Where(p => p.Name.IsLike("companyName")).List();

this behaves as I'd expect, and I can query over the name and get the matching results. However, when I do

session.QueryOver<Party>().Where(p => p.Name.IsLike("firstname lastname")).List();

The query doesn't match the Persons at all, but uses the mapping from the union-subclass of the company. So when parametrized with Party, the query seems to be essentially the same as when parametrized with Company (the WHERE-clause of the query is: WHERE this_.company_name = ((E'firstname lastname')::text))

Any pointers about where I might be going wrong and how to achieve what I'm after?


Solution

  • Apparently this is a known issue of NHibernate 3.x: https://nhibernate.jira.com/browse/NH-2354?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel