After spending quite a few hours going through the NHibernate source I was finally able to identify why RegisterKeyword("SQL_INTEGER")
did not work. The method Template.RenderWhereStringTemplate
is used to generate the formula SQL. This method calls ToLowerInvariant()
on each string token it processes, so when the method checks the list of reserved keywords it looks for sql_integer
and therefore cannot find it. After changing the the call to RegisterKeyword("sql_integer")
in our custom dialect the correct SQL was generated:
CONVERT(hostplacem0_.alloc_code, SQL_INTEGER)
For completeness I also checked to see if it was possible to inject in new keywords by accessing the dialect class in SessionFactoryImpl
and calling RegisterKeyword
by reflection, i.e.
var factory_impl = factory as SessionFactoryImpl;
if (factory_impl != null)
{
MethodInfo mInfoMethod = typeof(Dialect).GetMethod(
"RegisterKeyword",
BindingFlags.Instance | BindingFlags.NonPublic,
Type.DefaultBinder,
new[] { typeof(string) },
null);
mInfoMethod.Invoke(factory_impl.Dialect, new object[] { "sql_integer" });
}
While this code works NHibernate still emits the incorrect SQL. Unforunately it looks like NHibernate creates a new instance of the dialect everytime a dialect object is requested using the Dialect.GetDialect
method.
I guess the only way around this problem is to do what we did. Create your own dialect either completely, like in our situation, or by sub-classing from an existing dialect and adding the call for RegisterKeyword
into the constructor.