如何在NHibernate中映射到SortedList

本文关键字:映射 SortedList NHibernate | 更新日期: 2023-09-27 18:14:05

我有一个nHibernate父子表关系。父类目前正在将子类拉入List中,但我想根据表中的排序列将它们放入SortedList中。我如何改变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

编辑:数据被读入的类是:

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?

如何在NHibernate中映射到SortedList

nhibernate很好地支持您想要获得的内容。其实不是只有一种方法,有两种:

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"

扩展映射

这允许使用更多的用户友好的列(带有一些可编辑的值)用于在加载

期间对列表进行排序

请在这里查看更多内容:6.2。映射集合

EDIT:跟随问题编辑

c# SortedList映射再次被NHibernate支持。请参阅6.6节。分类收集

映射应该像这样

<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
  4. 上可用(作为只读)

这应该回答了关于字典的排序和键的问题…如果我错过了什么,请告诉我。

您应该使用<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, SetList

List具有排序语义,我猜您已经意识到,但是当不需要排序时,您通常会使用Set

因为Set规定每个项目只在集合中出现一次,所以很容易使用单个delete语句删除该项目的Id。Bag没有强制要求集合的唯一性,所以NHibernate删除一个项的唯一方法就是删除所有的项,然后重新添加每个不是被删除项的项。(相反,将一个项添加到Bag可以比使用Set更快,因为不需要强制惟一性)

Ayende (NHibernate的主要贡献者之一)不久前发布了这些:

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

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