惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
量子位
H
Help Net Security
Microsoft Azure Blog
Microsoft Azure Blog
MongoDB | Blog
MongoDB | Blog
小众软件
小众软件
爱范儿
爱范儿
博客园 - 【当耐特】
Vercel News
Vercel News
S
SegmentFault 最新的问题
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
GbyAI
GbyAI
博客园 - 叶小钗
博客园_首页
V
Visual Studio Blog
宝玉的分享
宝玉的分享
B
Blog
MyScale Blog
MyScale Blog
C
Check Point Blog
博客园 - 三生石上(FineUI控件)
L
LangChain Blog
V
V2EX

博客园 - EA_Games

ASP.NET常用代码 - EA_Games - 博客园 Oracle中的OMS的代理服务启动不了的问题 .Net术语大全 DataGrid中的数据导入到Word和Excel_C# NHibernate 进阶 用Nhibernate怎么实现数据的添加、删除、修改简单程序 每个开发人员现在应该下载的十种必备工具 nhibernate入门系列: one-to-one映射 NHibernate快速指南 nhibernate入门系列: 对象持久化操作 ASP.NET 安全认证(三) -- 一点补充(或者叫优化) ASP.NET 安全认证(一) ASP.NET 安全认证(二) Winform如何存入、读取SQL SERVER数据库图片 无法运行ASP.NET Web应用程序 选择VB.Net还是C# ASP.NET中在线用户统计 在asp.net中访问sql server - EA_Games - 博客园 ASP.NET数据库中图片存储及读取
nhibernate入门系列: one-to-many映射
EA_Games · 2005-11-22 · via 博客园 - EA_Games

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

                                                    [ 2005-04-27 15:37:48 | 作者: NeoWing ]

        数据库中的主从表就是一对多的关系了,这种关系在按范式设计的数据库中是十分常见的.在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 = new Hashtable();

} //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是可以单独使用的, 我们建议只要是子表, 就应该使用, 这样可以保证数据的完整性.