I’m using <dynamic-component> elements to provide end-users the capacity to extend the functionality of our product by adding fields to the database.
A simplified version of our mapping is:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Caselle.Am0.DTO" assembly="Caselle.Am0.DTO" schema="dbo">
<class name="Asset" table="[tblAsset]" lazy="true">
<id name="ID" column="ID" type="Int32">
<generator class="native" />
</id>
<property name="AssetNumber" column="[AssetNumber]" type="long" not-null="true" />
<dynamic-component insert="true" update="true" name="UserDefinedFields" />
<many-to-one name="Classification" column="tblClassificationID" class="Lib.DTO.Classification, Lib.DTO" cascade="none" />
</class>
<class name="Classification" table="[tblClassification]" lazy="true">
<id name="ID" column="ID" type="Int32">
<generator class="native" />
</id>
<property name="Name" column="[Classification]" type="String" not-null="true" length="20" />
<dynamic-component insert="true" update="true" name="UserDefinedFields" />
<set name="Assets" table="tblAsset" lazy="true" cascade="all-delete-orphan" inverse="true">
<key column="tblClassificationID"/>
<one-to-many class="Lib.DTO.Asset, Lib.DTO"/>
</hibernate-mapping>
The classes look something like this:
public class Asset
{
public virtual long AssetNumber{get; set;}
public Classification Classification {get; set;}
public virtual IDictionary UserDefinedFields {get; set;}
}
public class Classification
{
public virtual string Name {get; set;}
public virtual ICollection<Asset> Assets {get; private set;}
public virtual IDictionary UserDefinedFields {get; set;}
}
The problem I’m running into is that now users want to use our filtering tools on their custom fields, and I get a QueryException(Could not resolve property ‘X’) when I run the following query:
var query = session.CreateCriteria<Asset>()
.Create Alias("c", "Classification")
.Add(Restrictions.Eq(Projections.Property("c.X"), "value")
.ToList<Asset>();
Is it possible to do this kind of a projection? How else might I write this query (I really like the Criteria API, since I’m generating this query on the fly, but if I have to work some other way…)?
I don’t think you want to use the projection there. Try swapping out
.Add(Restrictions.Eq(Projections.Property("c.X"), "value")for
.Add(Restrictions.Eq("c.UserDefinedFields.X", "value")