Использование NHibernate для сопоставления столбца nChar с перечисляемым типом - PullRequest
0 голосов
/ 18 марта 2010

Я пытаюсь сопоставить таблицу frp, БД SQL Server 2005, с классом, содержащим перечисление:

public class MyClass{
private YesNoOptional addressSetting;
public YesNoOptional AddressSetting{
    {get; set;}
}

}

public enum YesNoOptional {
    Yes,
    No,
    Optional
}

Это будет диктовать, что в соответствующий столбец будет вставлено одно из трех значений - «Y», «N», «O». Этот столбец имеет тип nchar (1).

Мой файл сопоставления выглядит примерно так (addressSetting - это свойство, вызывающее проблему):

  <class name="IncidentDefinition" table="IR_INCIDENT_DEF" lazy="false" >
    <id name="Guid" column="INT_GUID" >
      <generator class="guid"></generator>
    </id>
    <property name="Reference" column="INT_REF" ></property>
    <property name="Description" column="INT_DESCRIPTION"  ></property>

    <property name="AddressSetting" column="INT_ADDRESS_REQ" ></property>

    <property name="Active" column="INT_ACTIVE" type="YesNo"></property>
    <property name="PinDocId" column="INT_PIN_DOC_ID"></property>
  </class>  

Используя приведенную выше конфигурацию, я получаю следующую ошибку: NHibernate.ADOException: не удалось инициализировать коллекцию: System.FormatException: входная строка была в неправильном формате ..

Если я попытаюсь отобразить перечисление с помощью пользовательского типа, например, так:

<property name="AddressSetting" column="INT_ADDRESS_REQ" type="ML.Types.YesNoOptional, ML.Types" ></property>

Ошибка: System.FormatException: входная строка была в неправильном формате.

Далее, если я попытаюсь использовать определенный тип, например, так:

 <property name="AddressSetting" column="INT_ADDRESS_REQ" type="String" ></property>

Эта ошибка генерируется: NHibernate.PropertyAccessException: тип System.String не может быть назначен свойству типа System.ArgumentException: объект типа 'System.String' нельзя преобразовать в тип 'ML.Types.YesNoOptional' ..

В крайнем случае я попытался указать тип как символ:

<property name="AddressSetting" column="INT_ADDRESS_REQ" type="Char" ></property>

Это работает немного лучше, так как в нем не выдается ошибка, однако вместо того, чтобы возвращать символ из таблицы и отображать его в перечисляемом типе, вместо него возвращается значение символа ASCII - так что Y представляется как 89 !

Я надеюсь, что кто-то может объяснить, что я делаю неправильно и \ или как, почему это происходит, пожалуйста?

Спасибо

Morris

Ответы [ 4 ]

1 голос
/ 21 марта 2010

Реализует IUserType, а затем присваивает значение query.substitutions для простого запроса

<property name="query.substitutions">yes 'Y', no 'N', opt 'O'</property>
1 голос
/ 19 марта 2010

Вы можете подумать о создании собственного IUserType для этого. Я написал сообщение в блоге о том, как сделать что-то подобное с DateTime, и вы можете скопировать + вставить 90% кода: http://blog.statichippo.com/archive/2010/01/07/calendar-sizes-datetime-vs-nullable-sqldatetime-in-nhibernate.aspx

В основном, самые большие изменения произошли в NullSafeSet и NullSafeGet. В NullSafeSet вы захотите переключить свой enum, а затем соответственно установить значение DB в Y / N / O. И в вашем NullSafeGet вы захотите переключить результат (вероятно, неплохая идея сначала запустить Char.ToLower ()) и вернуть соответствующее перечисление.

Простой, мощный и не мешающий вашей модели работать с вашей БД.

0 голосов
/ 19 марта 2010

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

Как я объяснил выше, было возвращено значение кода ASCII, поэтому для Y я получил значение 89 и расширил перечисление для использования этих значений следующим образом:

public enum YesNoOptional { Да = 89, Нет = 79, Необязательно = 78 }

Это заполняет значения правильно, когда они возвращаются из базы данных

0 голосов
/ 18 марта 2010

Я полагаю, это потому, что вы пытаетесь сопоставить строку с перечислением. По умолчанию базовый тип типа перечисления является целым числом.

Вы могли бы использовать что-то вроде Nullable<bool> для достижения того, что вы хотите, вместо перечисления. Но если вы действительно хотите использовать один из них, AND , оставив поле поддержки в виде столбца nchar(1), я бы сделал запрос наподобие:

SELECT intAddressSetting = CASE AddressSetting WHEN 'Y' THEN  1
                                               WHEN 'N' THEN  0
                                               ELSE -1 
                           END
 FROM table

И используйте это поле для сопоставления с вашим перечислением.

Измените значения по мере необходимости, обычно значение "НЕТ" имеет значение 0, а значение "ДА" равно 1, но в вашем перечислении они обращены, и значение Optional имеет значение 2, которое сделал бы -1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...