代码改变世界

NHibernate3剖析:Mapping篇之集合映射基础(4):Map映射

2010-05-12 21:56 by 李永京, ... 阅读, ... 评论, 收藏, 编辑

本节内容

系列引入

NHibernate3.0剖析系列分别从Configuration篇、Mapping篇、Query篇、Session策略篇、应用篇等方面全面揭示NHibernate3.0新特性和应用及其各种应用程序的集成,基于NHibernte3.0版本。如果你还不熟悉NHibernate,可以快速阅读NHibernate之旅系列文章导航系列入门,如果你已经在用NHibernate了,那么请跟上NHibernate3.0剖析系列吧。

Dictionary映射

这节我们介绍Dictionary映射,一般而言,Domain中的System.Collections.Generic.IDictionary<TKey,TValue>集合类型使用Map来映射。

映射纲要

Map映射有三个部分:集合外键(Collection foreign keys)、索引字段(index column)、集合元素(Collection element)。

集合外键(Collection foreign keys),通过<key>映射,其column属性命名方式一般采用"集合持有者类名+Id"命名方式。

索引字段(index column),即字典的键:

  • 值类型,通过<map-key>或者<composite-map-key>映射。
  • 引用类型,通过<map-key-many-to-many>映射。

集合元素(Collection element),即字典的值:

  • 值类型,其声明周期完全依赖于集合持有者,通过<element>或<composite-element>映射。
  • 引用类型,被作为集合持有的状态考虑的,只有两个对象之间的“连接”,具有其自己的生命周期,通过<one-to-many>或<many-to-many>映射。

案例分析

案例一:DictionaryOfElements

Domain定义中,集合元素一般是单一元素(Elements)类型,即.Net基本类型(string、int、double等等)。

//Code Snippets Copyright http://lyj.cnblogs.com/
public class DictionaryOfElements
{
    public int Id { get; set; }
    public IDictionary<string, DateTime> Elements { get; set; }
}

映射简单写法:

//Code Snippets Copyright http://lyj.cnblogs.com/
<class name="DictionaryOfElements">
  <id name="Id" type="Int32">
    <generator class="hilo" />
  </id>
  <map name="Elements" table="DictionaryOfElementsElements">
    <key column="DictionaryOfElementsId" />
    <map-key type="String" />
    <element type="DateTime" />
  </map>
</class>

字典的键使用<map-key>映射,我们必须指定type,其column缺省列名为idx。

字典的值为单一元素类型,这时使用<element>映射,我们应该至少type类型,其column缺省列名为id。

数据库架构:

DictionaryOfElements

案例二:DictionaryOfComponents

Domain定义中,集合元素一般是组件(Component)类型,也就是值类型。

//Code Snippets Copyright http://lyj.cnblogs.com/
public class DictionaryOfComponents
{
    public int Id { get; set; }
    public IDictionary<string, ComponentDictionary> Components { get; set; }
}

public class ComponentDictionary
{
    public string StringProperty { get; set; }
    public int IntProperty { get; set; }
}

映射简单写法:

//Code Snippets Copyright http://lyj.cnblogs.com/
<class name="DictionaryOfComponents">
  <id name="Id" type="Int32">
    <generator class="hilo" />
  </id>
  <map name="Components">
    <key column="DictionaryOfComponentsId" />
    <map-key type="String" />
    <composite-element class="ComponentDictionary">
      <property name="StringProperty" />
      <property name="IntProperty" />
    </composite-element>
  </map>
</class>

字典的键使用<map-key>映射,我们必须指定type,其column缺省列名为idx。

字典的值为组件(Component)类型,使用composite-element映射,需要指明组件类名,然后映射其组件属性。

数据库架构:

DictionaryOfComponents

案例三:DictionaryOfOneToMany

Domain定义中,集合元素是指向另一个实体OneToManyDictionary的引用。这里设置为一对多关系。

//Code Snippets Copyright http://lyj.cnblogs.com/
public class DictionaryOfOneToMany
{
    public int Id { get; set; }
    public IDictionary<string, OneToManyDictionary> OneToMany { get; set; }
}

public class OneToManyDictionary
{
    public int Id { get; set; }
}

映射简单写法:

//Code Snippets Copyright http://lyj.cnblogs.com/
<class name="DictionaryOfOneToMany">
  <id name="Id" type="Int32">
    <generator class="hilo" />
  </id>
  <map name="OneToMany">
    <key column="DictionaryOfOneToManyId" />
    <map-key type="String" />
    <one-to-many class="OneToManyDictionary" />
  </map>
</class>
<class name="OneToManyDictionary">
  <id name="Id" type="Int32">
    <generator class="hilo" />
  </id>
</class>

字典的键使用<map-key>映射,我们必须指定type,其column缺省列名为idx。

字典的值是引用类型,DictionaryOfOneToMany和OneToManyDictionary定义一对多关系,使用<one-to-many>映射,指明关联的对象。

数据库架构:

DictionaryOfOneToMany

案例四:DictionaryOfManyToMany

Domain定义中,集合元素是指向另一个实体ManyToManyDictionary的引用。这里设置为多对多关系。

//Code Snippets Copyright http://lyj.cnblogs.com/
public class DictionaryOfManyToMany
{
    public int Id { get; set; }
    public IDictionary<string, ManyToManyDictionary> ManyToMany { get; set; }
}

public class ManyToManyDictionary
{
    public int Id { get; set; }
}

映射简单写法:

//Code Snippets Copyright http://lyj.cnblogs.com/
<class name="DictionaryOfManyToMany">
  <id name="Id" type="Int32">
    <generator class="hilo" />
  </id>
  <map name="ManyToMany">
    <key column="DictionaryOfManyToManyId" />
    <map-key type="String" />
    <many-to-many class="ManyToManyDictionary" column="ManyToManyDictionaryId" />
  </map>
</class>
<class name="ManyToManyDictionary">
  <id name="Id" type="Int32">
    <generator class="hilo" />
  </id>
</class>

字典的键使用<map-key>映射,我们必须指定type,其column缺省列名为idx。

字典的值为引用类型,我们设置多对多关系,这时需要一个“中间表”来存储这两个对象的关系。

数据库架构:

DictionaryOfManyToMany

案例五:DictionaryKeyManyToMany

Domain定义中,集合Key是指向另一个实体ManyToManyDictionary的引用。这里设置为多对多关系。

//Code Snippets Copyright http://lyj.cnblogs.com/
public class DictionaryKeyManyToMany
{
    public int Id { get; set; }
    public IDictionary<KeyManyToManyDictionary, string> KeyManyToMany { get; set; }
}

public class KeyManyToManyDictionary
{
    public int Id { get; set; }
}

映射简单写法:

//Code Snippets Copyright http://lyj.cnblogs.com/
<class name="DictionaryKeyManyToMany">
  <id name="Id" type="Int32">
    <generator class="hilo" />
  </id>
  <map name="KeyManyToMany">
    <key column="DictionaryKeyManyToManyId" />
    <map-key-many-to-many class="KeyManyToManyDictionary" />
    <element type="String" />
  </map>
</class>
<class name="KeyManyToManyDictionary">
  <id name="Id" type="Int32">
    <generator class="hilo" />
  </id>
</class>

字典的键为引用类型,我们设置多对多关系,使用<map-key-many-to-many>映射,并指明class名。

字典的值为为单一元素类型,使用<element>映射。

数据库架构:

DictionaryKeyManyToMany

结语

这篇文章介绍NHibernate中的集合映射之Dictionary映射。结合前面三篇一起总结了NHibernate中四种集合的映射基础,有人会问这四篇代码看起来基本差不多,其实不是这样的,每种案例都是一个特殊的Domain应用,因为在我了解中,大多数人设计Domain还是十分简单,没有什么复杂的结构,有的甚至为了赶项目,找个生成工具生成比较糟蹋的Mapping,自己对Mapping还搞不清生成出来的Mapping代码,于是到处询问,贴出那些生成出来的代码,说实话,这非常反感。我们应该学会NHibernate的基本映射,所以我总结按其分类一一举例,并写出比较正规的Mapping,需要给大家有所指引和参考。

接下来开始从应用角度分析它们的不同。

希望本文对你有所帮助。