多对一公式的表名附加到SQL关键字

时间:2013-03-18 15:08:55

标签: nhibernate nhibernate-mapping advantage-database-server

我正在使用遗留数据库,我正在尝试将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注册为关键字,但这没有帮助。

1 个答案:

答案 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的调用添加到构造函数中。