3

私はレガシーデータベースを使用しており、多対1のマッピングのためにcharをintに変換しようとしています。これは素晴らしいアイデアではないことはわかっていますが、スキーマをそのまま使用しています。

次のマッピングでこれを実行しようとしましたが、NHibernateがテーブル名のエイリアスをキーワードに追加していることがわかりましたSQL_INTEGER

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

SQLを生成します

CONVERT(hostplacem0_.alloc_code, hostplacem0_.SQL_INTEGER)

私はこの投稿を見つけましたが、解決策は私の状況では実行可能なものではありません。

注意すべき点の1つは、NHibernateがそのままではサポートしていないため、使用するDBMS(Sybase Advantage Database Server)用に独自の方言を使用していることです。したがって、この問題に対処するためにこれを修正するオプションがあります。私はすでに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を出力します。残念ながら、NHibernateは、Dialect.GetDialectメソッドを使用して方言オブジェクトが要求されるたびに、方言の新しいインスタンスを作成するように見えます。

この問題を回避する唯一の方法は、私たちがやったことをすることだと思います。私たちの状況のように完全に、または既存の方言からサブクラスRegisterKeyword化してコンストラクターに呼び出しを追加することにより、独自の方言を作成します。

于 2013-03-19T09:49:00.150 に答える