我正在使用遗留数据库,我正在尝试将char转换为int以进行多对一映射。我知道这不是一个好主意,但我坚持使用架构。
我尝试使用以下映射执行此操作,但发现NHibernate正在将表名别名添加到关键字SQL_INTEGER
。
<many-to-one name="host" formula="CONVERT(alloc_code, SQL_INTEGER)" />
生成SQL
CONVERT(hostplacem0_.alloc_code, hostplacem0_.SQL_INTEGER)
我发现了this帖子,但解决方案对我的情况来说并不可行。
有一点需要注意的是,我们已经为我们使用的DBMS(Sybase Advantage数据库服务器)推出了我们自己的方言,因为NHibernate不支持开箱即用。因此,我可以选择修改此问题来解决此问题。我已经尝试将SQL_INTEGER
注册为关键字,但这没有帮助。
答案 0 :(得分:1)
经过NHibernate源码花了几个小时后,我终于找到了RegisterKeyword("SQL_INTEGER")
无效的原因。方法Template.RenderWhereStringTemplate
用于生成公式SQL。此方法在它处理的每个字符串标记上调用ToLowerInvariant()
,因此当方法检查保留关键字列表时,它会查找sql_integer
,因此无法找到它。在我们的自定义方言中将调用更改为RegisterKeyword("sql_integer")
后,生成了正确的SQL:
CONVERT(hostplacem0_.alloc_code, SQL_INTEGER)
为了完整性,我还检查了是否可以通过访问SessionFactoryImpl
中的方言类并通过反射调用RegisterKeyword
来注入新的关键字,即
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" });
}
虽然这段代码有效但NHibernate仍会发出错误的SQL。不幸的是,每当使用Dialect.GetDialect
方法请求方言对象时,NHibernate都会创建一个新的方言实例。
我想解决这个问题的唯一方法就是做我们做的事情。完全创建自己的方言,就像在我们的情况下一样,或者通过从现有方言中进行子类化并将RegisterKeyword
的调用添加到构造函数中。