Extending the LINQ provider

Sometimes you will need a more sophisticated way to translate method calls to HQL. In this recipe, we will show you how to implement a custom LINQ to HQL generator that is able to do this.

Getting ready

Complete the Using custom dialect functions recipe.

How to do it…

  1. Create a new class library project named CustomLinqGenearatorExample.
  2. Install the NHibernate and log4net packages using the NuGet Package Manager Console by executing the following command:
    Install-Package NHibernate
    Install-Package log4net
    
  3. Create the DateTimeFunctionsGenerator class using the following code:
    public class DateTimeFunctionsGenerator
      : BaseHqlGeneratorForMethod
    {
      public DateTimeFunctionsGenerator()
      {
        SupportedMethods = new[]
        {
          ReflectionHelper.GetMethod<DateTime>(
            d => d.AddDays(0)),
          ReflectionHelper.GetMethod<DateTimeOffset>(
            d => d.AddDays(0)),
          ReflectionHelper.GetMethod<DateTime>(
            d => d.AddHours(0)),
          ReflectionHelper.GetMethod<DateTimeOffset>(
            d => d.AddHours(0)),
          ReflectionHelper.GetMethod<DateTime>(
            d => d.AddMinutes(0)),
          ReflectionHelper.GetMethod<DateTimeOffset>(
            d => d.AddMinutes(0)),
          ReflectionHelper.GetMethod<DateTime>(
            d => d.AddSeconds(0)),
          ReflectionHelper.GetMethod<DateTimeOffset>(
            d => d.AddSeconds(0)),
          ReflectionHelper.GetMethod<DateTime>(
            d => d.AddMilliseconds(0)),
          ReflectionHelper.GetMethod<DateTimeOffset>(
            d => d.AddMilliseconds(0)),
        };
      }
    
      public override HqlTreeNode BuildHql(
        MethodInfo method,
        Expression targetObject,
        ReadOnlyCollection<Expression> arguments,
        HqlTreeBuilder treeBuilder,
        IHqlExpressionVisitor visitor)
      {
        return treeBuilder.MethodCall(
          method.Name,
          visitor.Visit(targetObject).AsExpression(),
          visitor.Visit(arguments[0]).AsExpression());
      }
    }
  4. Create the CustomLinqtoHqlGeneratorsRegistry class using the following code:
    public class CustomLinqtoHqlGeneratorsRegistry 
      : DefaultLinqToHqlGeneratorsRegistry
    {
      public CustomLinqtoHqlGeneratorsRegistry()
      {
        this.Merge(new DateTimeFunctionsGenerator());
      }
    }
  5. Register the CustomLinqtoHqlGeneratorsRegistry into a configuration using the following code:
     cfg.SetProperty(
        Environment.LinqToHqlGeneratorsRegistry,
        typeof (CustomLinqtoHqlGeneratorsRegistry).
          AssemblyQualifiedName)

How it works…

In the constructor of DateTimeFunctionsGenerator, we define the methods that are supported by this HQL generator. In this case, we want to be able to handle AddDays, AddHours, AddMinutes, AddSeconds, and AddMilliseconds of DateTime, and DateTimeOfset types. We are using ReflectionHelper.GetMethod to extract the methods from the expression tree.

The BuildHql method of DateTimeFunctionsGenerator is responsible for translating our method call to the HQL expression.

Then we register our custom generator in the HQL generator registry. After that we register our custom registry to the configuration.

See also

  • Using custom dialect functions
  • Using custom functions in LINQ
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.157.142