3

我正在使用旧数据库,并尝试将 char 转换为 int 以进行多对一映射。我知道这不是一个好主意,但我坚持使用模式。

我尝试使用以下映射来执行此操作,但发现 NHibernate 正在将表名别名添加到关键字SQL_INTEGER中。

<many-to-one name="host" formula="CONVERT(alloc_code, SQL_INTEGER)" />

生成 SQL

CONVERT(hostplacem0_.alloc_code, hostplacem0_.SQL_INTEGER)

我找到了这篇文章,但解决方案不适用于我的情况。

需要注意的一点是,我们为我们使用的 DBMS(Sybase Advantage 数据库服务器)推出了自己的方言,因为 NHibernate 不支持开箱即用。因此,我可以选择修改它来解决这个问题。我已经尝试注册SQL_INTEGER为关键字,但没有帮助。

4

1 回答 1

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到构造函数中。

于 2013-03-19T09:49:00.150 回答