nhibernate入门系列: one-to-many映射

添加人:iyond五级(2401分)   添加时间:2007-05-21    阅读次数:2688  收藏此教程
数据库中的主从表就是一对多的关系了,这种关系在按范式设计的数据库中是十分常见的.在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.Save(parent);
}

public TestRemoveChild()
{
    Parent parent = new Parent();
    parent.Name = "test parent";

    Child child = new Child();
    child.Name = "test child";
    child.Parent = parent;

    Child child2 = new Child();
    child2.Name = "test child2";
    child2.Parent = parent;

    parent.Childs.Add(child, child);
    parent.Childs.Add(child2, child2);

    session.Save(parent);
    session.Close();

    int parentId = parent.ParentId;
    parent = (Parent)session.load(typeof(Parent), parentId);

    IDictionaryEnumerator e = parent.Childs.GetEnumerator();
    if (e.MoveNext)
    {
        Child child3 = (Child)e.Key;
        parent.Childs.Remove(child3); // 删除只是断开子类与父类的关联,并不会真正删除!
        Session.Delete(child3); // 此处代码未测试正确性。
        // Session.Save( parent );
    }
}

以上测试代码中session的相关操作请查看相关文档。

在使用one-to-many时, 因为子对象是随父对象一起加载的(使用lazy除外), 这在有些时候就不是很有必要了, 并且产生性能问题, 在实际应用中应该要考虑清楚.
而many-to-one是可以单独使用的, 我们建议只要是子表, 就应该使用, 这样可以保证数据的完整性.
1页 第1上一页1下一页
相关的教程: 入门 Nhibernate one-to-many 映射
收藏此教程

当前平均分: 0.0(0 次打分)

-5-4-3-2-1012345
评论主题
您的大名
您的评论
验证码 点击换一个验证码
知识库搜索: