日期:2009-01-09  浏览次数:20370 次

数据库中的主从表就是一对多的关系了,这种关系在按范式设计的数据库中是十分常见的.在nh中,通过one-to-many映射可以十分方便的处理这种关系,包括级联更新,删除等. 下面以一个简单的主从表来说明one-to-many的应用.

先来看看Parent类的映射信息:

<class name="Parent, assemblyname" table="Parents">
   <id type="Int32" column="parent_id" unsaved-value="0" name="ParentId">
      <generator class="identity" />
   </id>
   <property type="String" column="Name" name="Name"/>
   <set name="Childs" cascade="all" inverse="true" lazy="false">
      <key column="parent_id" />
      <one-to-many class="Child, AssemblyName" />
   </set>
</class>
one-to-many关系必须通过一个nh的集合类型来定义, 这里使用set.
在上面的映射文件中,定义级联类型为all,允许所有持久化操作级联到子类;inverse标记这个集合为双向关联中的一端;lazy为延迟加载(使用此特性时一定在注意会话的生存周期)。
key column为与子类关联的键列,这里为Parent的主键parent_id。

Parent的定义:

public class Parent {

   public Parent() {
   }

   public int ParentId {
      get { return parentId; }
      set { parentId = value; }
   }

   public string Name {
      get { return name; }
      set { name = value; }
   }

   public IDictionary Childs {
      get { return childs; }
      set { childs = value; }
   }

   private int parentId;
   private string name;
   private IDictionary childs;

} //class Parent
这里用一个数据字典(Dictionary)对象来保存由set集合指定的子对象;

再来看看Child类的映射信息:

<class name="Child, AssemblyName" table="Childs">
   <id type="Int32" column="child_id" unsaved-value="0" name="ChildId">
      <generator class="identity" />
   </id>
   <property type="String" column="Name" name="Name"/>
   <many-to-one
      name="Parent"
      column="parent_id"
      class="Parent, AssemblyName"
      unique="true"
   />
</class>
在many-to-one定义中,定义了与parent关联的列parent_id以及父类名称;unique指定与子类关联的父类是唯一的
这里并没有单独映射parent_id列,此列映射信息由many-to-one定义给出, 这样可以保证数据完整性.

Child 类的定义:

public class Child {

   public Child() {
   }

   public int childId {
      get { return childId; }
      set { childId = value; }
   }

   public string Name {
      get { return name; }
      set { name = value; }
   }

   public Parent Parent {
      get {
         if ( parent == null ) parent = new Hashtable();
         return parent;
      }
      set { parent = value; }
   }

   private int childId;
   private string name;
   private Parent parent;

} //class Child
下面给出了部分测试代码。

public TestCreate() {
   Parent parent = new Parent();
   parent.Name = "test parent";
 
   Child child = new Child();
   child.Name = "test child";
   child.Parent = parent;  // 必须设置父对象才能正确保存!

   parent.Childs.Add( child, child );

   session.