формула «многие к одному» имеет имя таблицы, добавленное к ключевому слову SQL

Я работаю с устаревшей базой данных и пытаюсь преобразовать char в int для сопоставления «многие к одному». Я знаю, что это не очень хорошая идея, но я застрял со схемой как есть.

Я попытался сделать это с помощью следующего сопоставления, но обнаружил, что NHibernate добавляет псевдоним имени таблицы к ключевому слову SQL_INTEGER.

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

Генерирует SQL

CONVERT(hostplacem0_.alloc_code, hostplacem0_.SQL_INTEGER)

Я нашел этот пост, но решение не работает один для моей ситуации.

Следует отметить, что мы создали собственный диалект используемой нами СУБД (Sybase Advantage Database Server), поскольку NHibernate не поддерживает его из коробки. Поэтому у меня есть возможность изменить это, чтобы решить эту проблему. Я уже пытался зарегистрировать SQL_INTEGER в качестве ключевого слова, но это не помогло.


person mickfold    schedule 18.03.2013    source источник
comment
Случайные мысли, но вы можете попробовать зарегистрировать функции в том же файле диалекта, см. github.com/nhibernate/nhibernate-core/blob/master/src/. Объявление str кажется интересным   -  person jbl    schedule 19.03.2013
comment
Спасибо за предложение @jbl. Оказывается, дело было в чувствительности к регистру. Пожалуйста, смотрите мой ответ ниже.   -  person mickfold    schedule 19.03.2013
comment
спасибо за продолжение   -  person jbl    schedule 19.03.2013


Ответы (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 в конструктор.

person mickfold    schedule 19.03.2013