2013-05-17 2 views
2

У меня есть отношение родительского дочернего элемента nHibernate. Родительский класс в настоящее время вытаскивает дочерние элементы в список, но я хочу поместить их в SortedList на основе столбца упорядочения в таблице. Как изменить файл сопоставления NHibernate, чтобы система узнала, в каком столбце я заказываю?Как сопоставить сортировку в NHibernate

текущие файлы сопоставления NHibernate являются:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
        namespace="Model.Configuration.Pages" 
        assembly="Model.Configuration"> 
    <joined-subclass 
      table="PageConfigurations" 
      name="PageConfiguration" 
      extends="Model.Configuration.Configuration.TargetedConfiguration" 
      lazy="false"> 
    <key column="TargetedConfigurationId" /> 

    <property name="SchemaVersion" /> 

    <property name="Template" type="System.String" length="50" /> 

    <property name="PageKey" type="System.String" length="50" /> 

    <property name="Percentage" /> 

    <bag name="Controls" cascade="all-delete-orphan" lazy="false" > 
     <key column="PageConfigurationId" /> 
     <one-to-many class="WidgetConfiguration"/> 
    </bag> 

    </joined-subclass> 
</hibernate-mapping> 

для родительской таблицы и:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
        namespace="Model.Configuration.Pages" 
        assembly="Model.Configuration"> 
    <class name="WidgetConfiguration" lazy="false" table="PageConfiguration_Widgets" discriminator-value="Default"> 
    <id name="Id" unsaved-value="0" type="int" > 
     <generator class="identity" /> 
    </id> 
    <discriminator column="ConfigurationType" /> 

    <property name="Slot" type="System.String" length="100" /> 
    <property name="WidgetTypeName" type="System.String" length="100"/> 
    <property name="ViewName" type="System.String" length="50" /> 
    <property name="SlotOrder" type="System.Int32" /> 
    </class> 
</hibernate-mapping> 

для дочерней таблицы.

Что нужно добавить к родительским или дочерним сопоставлениям, чтобы сообщить им, что новый столбец SlotOrder следует использовать в качестве ключевого поля при извлечении WidgetConfiguration в SortedList.

EDIT: Класс, данные считываются в это:

public class PageConfiguration : TargetedConfiguration 
{ 

    public PageConfiguration() 
    { 
     // replaced by SortedList 
     //Controls = new List<WidgetConfiguration>(); 
     Controls = new SortedList<int, WidgetConfiguration>(); 
    } 

    public string PageKey { get; set; } 
    public string Template { get; set; } 
    public int? Percentage { get; set; } 
    // replaced by SortedList 
    //public IList<WidgetConfiguration> Controls { get; set; } 
    public IDictionary<int, WidgetConfiguration> Controls { get; set; } 
    public int SchemaVersion { get; set; } 
} 

Обратите внимание, что List<WidgetConfiguration> было изменено на SortedList<int, WidgetConfiguration>. Как сообщить NHibernate, что, когда новый элемент добавлен в SortedList, что используемое значение ключа должно быть WidgetConfiguration.SlotOrder?

ответ

2

NHiberante имеет хорошую поддержку, что вы хотели бы получить. На самом деле это не только один из способов, есть два:

1) отображение с <list>

Используйте отображение списка, который поддерживает <index> столбец.это то же самое, как внутренний индекс в C# используется внутри List<T> объекта

Небольшой недостаток в том, что вы должны держать этот столбец, чтобы быть от 0 ... включая все номера. То же, что и основной объект C#. но он работает

Смотрите подробнее здесь: http://ayende.com/blog/4043/nhibernate-mapping-list и здесь для индексированных коллекций: http://nhibernate.info/doc/nh/en/index.html#collections-ofvalues

2) продолжить отображение с order-by="column_name asc|desc"

Это позволяет использовать некоторые более пользователя дружественного колонки (с некоторым редактируемым значением), которые будут использоваться для сортировки списка во время его загрузки

Plase, см. здесь: 6.2. Mapping a Collection

EDIT: следовать Вопрос Edit

C# SortedList отображение снова поддерживаемую NHibernate. Пожалуйста, зе раздел 6.6. Sorted Collections

Mapping должен выглядеть следующим образом

<map name="Controls" order-by="SlotOrder" lazy="true" cascade="all-delete-orphan"> 
    <key column="PageConfigurationId" /> 
    <index column="SlotOrder" type="System.Int32"/> 
    <one-to-many class="WidgetConfiguration"/> 
</map> 

в SlotOrder теперь управляется Родителя. Он играет роль ключа Элементы управленияSortedList. Таким образом, мы должны изменить свое отображение быть только для чтения (только одна точка редактирования времени должна существовать)

<class name="WidgetConfiguration" ...> 
    ... 
    <property name="SlotOrder" type="System.Int32" insert="false" update="false" /> 

Имея это отображение, мы можем добавить новый элемент в Controls коллекции:

WidgetConfiguration config = ...; 
PageConfiguration pageConfig = ...; 

pageConfig.Controls[config.SlotOrder] = config; 
session.Update(pageConfig); 

Так,

  1. мы составили карту SortedList (в интерфейс факт IDictionary<,>),
  2. SlotOrder используется в качестве ключа (вставляется, обновляется NHibernate) и
  3. доступны (как неизменяемые) на WidgetConfiguration

Это должно ответить на вопрос о сортировка и ключи словарей ... пожалуйста, дайте мне знать, если я что-то пропустил ...

+0

Не пропустил ничего ... спасибо –

+0

Замечательно, что он работает! –

1

Вы хотели бы использовать <List /> вместо <Bag />

<bag name="Controls" cascade="all-delete-orphan" lazy="false"> 
    <key column="PageConfigurationId" /> 
    <one-to-many class="WidgetConfiguration" /> 
    <index column="SlotOrder" /> 
</bag> 

Я заметил, что вы отображения коллекции в настоящее время в качестве Bag. NHibernate поддерживает три вида секвенировано-коллекций - Bag, Set и List

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

Поскольку Set указывает, что каждый элемент находится в коллекции только один раз, очень легко удалить элемент, используя единую инструкцию удаления на идентификаторе этого элемента. A Bag не требует уникальности коллекции, поэтому единственный способ для NHibernate удалить элемент - удалить все, а затем повторно добавить каждый элемент, который не был удаленным элементом. (Обратное добавление элемента к Bag может быть быстрее, чем при использовании Set, потому что уникальность не должна быть исполнена)

Ayende (один из основных вкладчиков в NHibernate) отправила их некоторое время назад:

http://ayende.com/blog/3943/nhibernate-mapping-set

http://ayende.com/blog/4043/nhibernate-mapping-list

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