Отображение коллекции перечислений в NHibernate - PullRequest
3 голосов
/ 27 сентября 2010

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

У меня есть класс Widget, сопоставленный с таблицей Widget. Существует также перечисление WidgetType, и один экземпляр Widget может иметь много WidgetTypes, сопоставленных через свойство WidgetTypes. Свойство необходимо сопоставить с отдельной таблицей WidgetTypeRef с двумя целочисленными столбцами: WidgetId и WidgetType.

public class Widget
{
  /* omitted */
  public IList<WidgetType> WidgetTypes { get; set; }
}
public enum WidgetType
{
  SomeType = 0,
  SomeOtherType = 1,
  YetOneMoreType = 2
}
public partial class WidgetMapping : IAutoMappingOverride<Widget>
{
  public void Override(AutoMapping<Widget> mapping)
  {
    /* omitted */
    mapping.HasMany(w => w.WidgetTypes)
      .Table("WidgetTypeRef")
      .KeyColumn("WidgetId")
      .Element("WidgetType");
  }
}

У меня нет контроля над схемой БД; схема не может быть изменена. Схема должна хранить целочисленные значения WidgetTypes, связанных с Widget, и не может быть преобразована для соответствия строковой версии перечисления. Я очень стараюсь сохранять строгую типизацию перечисления и избегаю создания новой сущности для таблицы Ref.

Другие классы имеют основанные на перечислении свойства типа, которые работают с конфигурацией ".CustomType (typeof (someTypeEnum)"), но в сопоставлении HasMany отсутствует свойство CustomType. При использовании этого сопоставления HasMany запросы в коллекцию throw a " Не удалось определить тип элемента "исключение.

Это вообще возможно? Как должна быть установлена ​​собственность? Как настроить отображение Fluent? Как запросить в коллекции (мой запрос требует только эквивалент Any или Contains)?

1 Ответ

2 голосов
/ 27 сентября 2010
public class EnumToIntConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum);
    }

    public void Apply(IPropertyInstance target)
    {
        target.CustomType(target.Property.PropertyType);
    }
}

Используя это соглашение, имея следующий Enum:

public enum Status
{
    Inactive = 0,
    Active = 1,
    Canceled = 2
}

И настроить его так (должно работать и с отображениями Fluent):

var cfg = Fluently.Configure()
    .Database(configurer)
    .Mappings(m =>
    {
        m.AutoMappings.Add(AutoMap.Assemblies(Assembly.GetExecutingAssembly())
            .Where(type => AutomapAssemblies.Contains(type.Namespace))
            .Conventions.Add<EnumToIntConvention>()  // Magic code goes here!
            .Conventions.Add());
    });

Сохранит значение integer вместо значения string.

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