Description
As of v5.3+ custom equality (and comparison) method handling is no longer possible for non-primitive types.
Let me unpack that.
We have a custom HQL generator implemented for object.Equals
, since that isn't supported by NH directly.
The reason we need it is due to custom code that generates LINQ query expressions which need to be both C# and NH compatible, so in some cases we must use object.Equals(object)
to correctly test for equality.
An example generated expression might look equivalent to e => (MyEnum.A).Equals((object)e.MyEnumProp)
Prior to v5.3.0 this worked fine for us.
After v5.3.0 this causes us errors, specifically when the mapped property is a String Enum type.
Some investigation led me to the following code
https://github.com/nhibernate/nhibernate-core/blob/5.3.8/src/NHibernate/Linq/Visitors/ParameterTypeLocator.cs#L249
This method of the visitor is hit prior to evaluating the types of the parameters.
It appears to be building a dictionary of "related" expression subtrees so that the parameter evaluator can figure out that Enum.A
(a constant, and therefore an SQL parameter) is related to e.MyEnumProp
(a mapped property) and can use the NH mapping to convert the parameter to the correct IType
.
Only this branch never runs because object.Equals(object)
is not on the hard-coded list of methods.
As a consequence, no relationship is added between the calling object and the mapped property argument.
Lacking any relationships, the parameter type evaluation falls back to guessing and, in this case, guesses that the parameter should be EnumType
instead of EnumStringType
. This generates SQL that attempts to compare a string column with an int parameter, with errors or bad results depending on the DB.