Jordi
Jordi

Reputation: 23247

Extend NHibernate Linq Provider

Might anybody provide some example in order to extend Hibernate Linq Provider for asking for whichever field [equals | lt | gt | notEquals ...] some_value. I.e:

this.session.Query<C>.Where(c => c.WhichEverField().Equals(1));

where WhichEverField() would be an extension method.

Any ideas?

Upvotes: 1

Views: 955

Answers (2)

Fr&#233;d&#233;ric
Fr&#233;d&#233;ric

Reputation: 9864

You may check out among this list if any of those extensions possibilities allows you to meet your goal.

But I doubt this is doable, if I have correctly understood your question. I do not know of any db syntax handling "whichever column" semantic, so I do not see how could it be possible to convert a LINQ extension having such a semantic to a SQL query having it too (which would moreover require a HQL extension since works by converting the LINQ query to HQL).

If you intend to handle that semantic directly in your LINQ extension by generating a many or comparison criteria inside it, it does not look possible to me either with your proposed c.WhichEverField().Equals(1).
Not only you would then have to use something like AlexDev answer. But also you will have to do type inspection on arguments and non trivial HqlTree building inside the BuildHql method.
And then, it will fail, because at the point where the BuildHql method would be called for your WhichEverField extension as you have defined it, you will have no idea of which comparison have to be done on your operands.

Maybe with a c.WhichEverField(SomeComparisonTypeEnum.Equal, 1) extension, you could handle that, but that will not be an easy feat anyway.
If this may help, you can find more extension examples (from me) here and by following the other links there, but none of them have the level of complexity of your demand.

Upvotes: 1

AlexDev
AlexDev

Reputation: 4717

This is a class I once wrote which allows you to use Convert.ToInt64() in a query:

public class ConvertToInt64HqlGenerator : BaseHqlGeneratorForMethod
{
    public ConvertToInt64HqlGenerator()
        : base()
    {
        this.SupportedMethods = new[] { ReflectionHelper.GetMethodDefinition(() => Convert.ToInt64("")),
                                        ReflectionHelper.GetMethodDefinition(() => Convert.ToInt64(0)),
                                        ReflectionHelper.GetMethodDefinition(() => Convert.ToInt64(0M))};
    }

    public override HqlTreeNode BuildHql(MethodInfo method,
                                            Expression targetObject,
                                            ReadOnlyCollection<Expression> arguments,
                                            HqlTreeBuilder treeBuilder,
                                            IHqlExpressionVisitor visitor)
    {
        return treeBuilder.Cast(visitor.Visit(arguments[0]).AsExpression(),typeof(Int64));
    }
}

To use it you need to create a Registry class:

public class MyLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public MyLinqToHqlGeneratorsRegistry()
        : base()
    {
        this.Merge(new ConvertToInt64HqlGenerator());
    }
}

And add it to your configuration:

Fluently.Configure().Database(msSQLconfig)
                    .ExposeConfiguration(c => c.LinqToHqlGeneratorsRegistry<MyLinqToHqlGeneratorsRegistry>())

Upvotes: 2

Related Questions