vendredi 1 avril 2016

LinqExtensionMethod not being resolved to StandardSQLFunction in Nhibernate 4.x

I'm updating a project from NHibernate 3.3.4 to 4.0.4

Our unit tests use SQLite, or production code uses Oracle. Oracle has a greatest function which SQLite does not have, so we have a custom SQLite Dialect with greatest aliased to max that we reference with a LINQ extension method. It works fine in 3.3.4, but does not work in 4.0.4. We have probably 30 other function registrations in the dialect that seem to work fine, just this one does not.

So in our SQLite dialect constructor we have:

RegisterFunction(GreatestFunctionExtension.GreatestFunction, new StandardSQLFunction("max", NHibernateUtil.DateTime));

The extension is defined as:

public static class GreatestFunctionExtension
{
    public const String GreatestFunction = "greatest";
    [LinqExtensionMethod(GreatestFunction)]
    public static DateTime GreatestDateTime(DateTime?[] expression)
    {
        throw new NotImplementedException("GreatestDateTime");
    }
}

So we use this down in the projection for the query which looks similar too

        Session.Query<TwoDateEntity>().Select(f => new
        {
            GreatestDate = GreatestFunctionExtension.GreatestDateTime(new[]
            {
                f.Date1,
                f.Date2
            })
        }).ToList();

This only results in the GreatestDateTime NotImplementedException in 4.x. It generates SQL like:

select twodateentity0_.DATE1 as col_0_0_, twodateentity0_.DATE2 as col_1_0_ from TWO_DATES twodateentity0_

Then it takes those two values and seems to pass them into the extension method.

In 3.3.4 it instead looks like:

select max(twodateentity0_.DATE1, twodateentity0_.DATE2) as col_0_0_ from TWO_DATES twodateentity0_

I believe it has something to do with the collection. If I change it from max to count, and switch the parameters to a single value, it seems to function correctly. I've also tried switching from an Array to a List, but it ends in the same result.

Aucun commentaire:

Enregistrer un commentaire