For a project that I’m developing, I have to use Linq to create some specifications. Now I have a Dictionary on which I have to search the values. Since the default Linq implementation for NHibernate doesn’t support the ContainsValue function, I decided to create my own.
So I created a class named ContainsValueGenerator which derived from BaseHqlGeneratorForMethod as follows:
public class ContainsValueGenerator : BaseHqlGeneratorForMethod
{
public ContainsValueGenerator()
{
SupportedMethods = new[] { ReflectionHelper.GetMethodDefinition(() => new Dictionary<object, object>().ContainsValue(null)) };
}
public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
//Session.CreateQuery("from Message m where 'aDictionaryValue' in elements(m.Dictionary)");
HqlTreeNode hqlTreeNode = treeBuilder.Elements(); // TODO include dictionary here?
return treeBuilder.In(visitor.Visit(arguments[0]).AsExpression(), hqlTreeNode);
//return treeBuilder.In(visitor.Visit(arguments[0]).AsExpression(), treeBuilder.Indices(visitor.Visit(targetObject).AsExpression())); ContainsKey Method implementation
}
}
I looked at the source code from Nhibernate and took the ContainsKey method implementation. The Hqlsyntax is very similar to the ContainsKey syntax. The only thing that needs to change (I guess) is, instead of the treebuilder.Indices(), I have to use the treebuilder.Elements(shown in comments).
That’s where I’m stuck; I can’t provide the ElementsExpression with my own Dictionary.
How can I create a HqlTreeNode that takes advantage of a Elements expression?
Thanks in advance,
Rob Van Pamel
The solution is to create your own HqlElements class that inherits from HqlExpression. In fact it is just a copy of the HqlIndices class.
The tricky part is to add this as property to the HqlTreeBuilder class. Therefore you can use an extension method. This contains one ugly piece of code the get the factory of the HqlTreeBuilder with reflection.
Your generator can now be changed to:
The best solution would be that this piece of code would make it into NHibernate itself. Maybe I’ll add a patch to GitHub for that.