Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate 3, Dynamic-Component, Dictionaries, and LINQ Queries

I've got this entity with a <dynamic-component> entry and a number of properties on it. It's being consumed on the entity class as an IDictionary.

The mapping works fine and everything is hunky dory until I go to query based on values in this dictionary.

First I tried the following linq query:

repository.Where(x => x.Specifications[key] == value) 

To query against it. (Specifications is the dynamic component) The query resulted in the following error:

Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'NHibernate.Type.ComponentType' to type 'NHibernate.Type.CollectionType'.

Figuring this might be outside the bounds of the Linq Provider I then went on to build a BaseHqlGeneratorForMethod to handle a custom linq extension for it.

It was built up by using the treeBuilder.Dot(...) AST like this:

var specificationExpression = 
  treeBuilder.Dot( 
     visitor.Visit(arguments[0]).AsExpression(), 
     treeBuilder.Ident("Specifications")).AsExpression(); 
var targetExpression = 
  treeBuilder.Dot( 
    visitor.Visit(arguments[0]).AsExpression(), 
    treeBuilder.Ident(keyExpression.Value.ToString())).AsExpression(); 

This worked great for generating the right SQL except that the expression is cached so subsequent calls to this function would compare all the values against the first key.

From here I found the treeBuilder.DictionaryItem(...) AST Node and built the following:

var specificationExpression = 
  treeBuilder.Dot( 
     visitor.Visit(arguments[0]).AsExpression(), 
     treeBuilder.Ident("Specifications")).AsExpression(); 
var specification = 
  treeBuilder.DictionaryItem(specificationExpression, key).AsExpression(); 

Once again I was met with the following error:

Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'NHibernate.Type.ComponentType' to type 'NHibernate.Type.CollectionType'.


The Question

What am I doing wrong here? Can <dynamic-component>' s not be queried on? Am I implementing this incorrectly? Could this be a bug I should report?

Mapping:

<dynamic-component name="Specifications"> 
  <property name="sp_Graphics" column="sp_Graphics" /> 
  <property name="sp_Weight" column="sp_Weight" /> 
</dynamic-component> 

Entity:

/// <summary> 
/// Specifications 
/// </summary> 
public virtual IDictionary Specifications { get; set; } 
like image 323
Aren Avatar asked Apr 18 '11 18:04

Aren


2 Answers

Due to a bug in the NHibernate linq provider you will not be able to use it to query dynamic components as of 3.1.0

https://nhibernate.jira.com/browse/NH-2664

Here is hoping that a fix can be worked out for version 3.2

In the meantime you should use a Criteria or HQL query.

like image 158
Danielg Avatar answered Nov 16 '22 12:11

Danielg


It's fixed since NHibernate 3.3.1 (valid link here : https://nhibernate.jira.com/browse/NH-2664)

like image 45
Sÿl Avatar answered Nov 16 '22 13:11

Sÿl