如何在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很好地支持您想要获得的内容。其实不是只有一种方法,有两种:
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);
- 我们已经映射了SortedList(实际上是接口
IDictionary<,>
), -
SlotOrder
被用作键(由NHibernate插入和更新)和 - 在WidgetConfiguration 上可用(作为只读)
这应该回答了关于字典的排序和键的问题…如果我错过了什么,请告诉我。
您应该使用<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
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