3

Я работаю с устаревшей базой данных и пытаюсь преобразовать символ в int для сопоставления много-к-одному. Я знаю, что это не отличная идея, но я придерживаюсь схемы, какой она есть.Формула много-к-одному имеет имя таблицы, добавленную к ключевому слову SQL

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

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

генерирует SQL

CONVERT(hostplacem0_.alloc_code, hostplacem0_.SQL_INTEGER) 

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

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

+0

Случайные мысли, но вы можете попробовать зарегистрироваться в одном и том же диалекте, см. Https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Dialect/MsSql2000Dialect.cs например , Объявление str кажется интересным – jbl

+0

Спасибо за предложение @jbl. Оказывается, это вопрос чувствительности к регистру. См. Мой ответ ниже. – mickfold

+0

thx для последующего наблюдения – jbl

ответ

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

Смежные вопросы