2013-05-17 40 views
2

我有一個nHibernate父子表關係。父類當前正在將子元素拉入列表中,但我想將它們放入基於表中排序列的SortedList中。如何更改NHibernate映射文件以讓系統​​知道我正在訂購哪一列?如何映射到NHibernate中的SortedList

目前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> 

的子表。

我需要添加到父映射或子映射中,以便讓他們知道在將WidgetConfiguration獲取到SortedList時,應該使用新的SlotOrder列作爲關鍵字段。

編輯:類的數據被讀入是:

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>列清單映射。這是一樣的,在List<T>對象

小缺點是內部使用的C#內部指數,你必須保持該列是從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

編輯:追隨問題編輯

C#SortedList映射由NHibernate的再次支持。請SE中的部分6.6. Sorted Collections

映射看起來應該是這樣

<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的支持三種排序的集合的 - BagSetList

名單已訂購語義,我想大家都知道,但不需要排序時,您通常會使用一個Set

因爲Set要求每個項目只能在一個集合中使用一次,所以使用該項目標識的單個刪除語句很容易刪除項目。 Bag不要求集合唯一性,所以NHibernate刪除一個項目的唯一方法是刪除所有內容,然後重新添加每個不是已刪除項目的項目。 (逆時將項目添加到一個Bag可以比使用Set更快,因爲唯一不必執行)

Ayende(的主要貢獻者的NHibernate中的一個)貼這些而回:

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

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