摘要:前面几篇文章简单的介绍了ActiveRecord中的基本映射以及构建配置信息,本文我们用ActiveRecord里面的BlogPost例子来实现One-Many/Many-One关联。

主要内容

1.准备数据表结构

2.编写实体类并介绍HasManyBlongsTo特性

3.构建配置信息

4.编写测试代码

 

一.准备数据表结构

在这个例子中,我们引入了两个对象BlogPost,它们之间的关系是一对多,即一个Blog有多篇Post。需要用到的数据表结构如下

Castle ActiveRecord学习实践(4):实现One-Many关系的映射CREATE TABLE Blogs (
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射    blog_id     
int IDENTITY(11PRIMARY KEY,
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射    blog_name   
varchar(50),
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射    blog_author 
varchar(50)
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射)
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射 
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
CREATE TABLE Posts (
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射    post_id        
int IDENTITY(11PRIMARY KEY,
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射    post_title     
varchar(50),
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射    post_contents  
text,
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射    post_categories 
varchar(50),
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射    post_blogid    
int FOREIGN KEY REFERENCES Blogs (blog_id),
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射    post_created   
datetime,
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射    post_published 
bit
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射)


二.编写实体类

首先我们来看Blog实体类的编写,需要用到HasMany特性,这时我们会在Blog实体类中定义一个Posts属性,用它来表示该Blog所发表的所有Posts,代码如下

 

Castle ActiveRecord学习实践(4):实现One-Many关系的映射[ActiveRecord("Blogs")]
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
public class Blog : ActiveRecordBase
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
}


HasManyAttribute说明

属性

说明

示例

Cascade

指明哪些操作会从父对象级联到关联的对象,相关的操作见后面,如果不指定,则为None

Cascade=ManyRelationCascadeEnum.All

Inverse

指定是否级联操作

Inverse =true|false

Schema

指定Schema的名字

Schema="ARDemo"

Table

指定持久化类所关联的数据库表名,如果表名与类名相同,可以省略

Table="posts"

ColumnKey

指定关联类的一个属性,这个属性将会和本外键相对应。

ColumnKey="post_blogid"

Where

指定一个附加SQLWhere子句

Where="IsPost = 0"

Lazy

指定是否延迟加载关联对象

Lazy=true|false


Cascade
的类型值有如下几种

类型

说明

None

不进行级联操作

SaveUpdate

进行级联Save/Update操作

Delete

进行级联Delete操作

All

进行级联Save/Update/Delete操作

AllDeleteOrphan

进行级联Save/Update/Delete操作,并删除无相关父对象的子对象

 

Post实体类中,我们需要定义一个Blog类型的属性,并且用到BlongsTo特性,即一个Post属于某一个Blog,代码如下:

Castle ActiveRecord学习实践(4):实现One-Many关系的映射[ActiveRecord("Posts")]
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
public class Post : ActiveRecordBase
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
}


BelongsToAttribute说明

属性

说明

示例

Cascade

指定级联操作

Cascade=CascadeEnum.SaveUpdate

Column

列名,外键字段名

BelongsTo("blogid")

Column="blogid"

Insert

是否允许增加

Insert=true|false

NotNull

是否允许为空

NotNull =true|false

OuterJoin

是否允许外连接抓取

OuterJoin=OuterJoinEnum.True

Unique

是否唯一

Unique =true|false

Update

是否允许更新

Update =true|false

 

Cascade类型如下

选项

说明

None

默认值,不进行级联操作

All

进行级联Save/Update/Delete操作

SaveUpdate

进行级联Save/Update操作

Delete

进行级联Delete操作

 

OuterJoin选项有三个:AutoTrueFalse

最后完整的Blog实体类如下

}

 

完整的Post类如下

Castle ActiveRecord学习实践(4):实现One-Many关系的映射
}


三.构建配置信息

这里我采用上篇中将过的XML配置方式

Castle ActiveRecord学习实践(4):实现One-Many关系的映射<?xml version="1.0" encoding="utf-8" ?>
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
<activerecord>
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射    
<config>
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射        
<add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射        
<add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射        
<add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射        
<add key="hibernate.connection.connection_string" value="Data Source=.;Initial Catalog=test;Integrated Security=SSPI" />
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射    
</config>
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
</activerecord>

 

四.编写测试代码

1.级联增加:新增一个Blog,并同时添加相关的Post到数据表中

Castle ActiveRecord学习实践(4):实现One-Many关系的映射[Test]
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
public void TestCascadingSave()
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
}

2.级联更新:
首先我们为一个已经存在的Blog增加多个Post

 

Castle ActiveRecord学习实践(4):实现One-Many关系的映射[Test]
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
public void TestCascadingUpdate()
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
}


当然上面的更新代码也可以这样去写:

Castle ActiveRecord学习实践(4):实现One-Many关系的映射[Test]
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
public void TestCascadingUpdate()
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
}


但是如果我们去掉post.Save()这句话,就会发现Post并没有增加到库中:

Castle ActiveRecord学习实践(4):实现One-Many关系的映射[Test]
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
public void TestCascadingUpdate()
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
}


此时,必须修改我们的Blog类,设置级联操作为SaveUpdate,上面的代码才可以正常执行

Castle ActiveRecord学习实践(4):实现One-Many关系的映射// Castle ActiveRecord学习实践(4):实现One-Many关系的映射Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射

Castle ActiveRecord学习实践(4):实现One-Many关系的映射[HasMany(
typeof(Post), Table="posts", ColumnKey="post_blogid",Cascade=ManyRelationCascadeEnum.SaveUpdate)]
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
public IList Posts
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
}


下面再测试一个删除某一个Blog的某些Post后,再保存

Castle ActiveRecord学习实践(4):实现One-Many关系的映射[Test]
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
public void TestCascadingUpdateDel()
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
}


上面这段代码测试可以通过,但是我们会发现表Posts中会有一些记录没有BlogId,修改Blog实体类重新设置级联操作,就可以正常删除了:

Castle ActiveRecord学习实践(4):实现One-Many关系的映射// Castle ActiveRecord学习实践(4):实现One-Many关系的映射Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射

Castle ActiveRecord学习实践(4):实现One-Many关系的映射[HasMany(
typeof(Post), Table="posts", ColumnKey="post_blogid",Cascade=ManyRelationCascadeEnum.AllDeleteOrphan)]
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
public IList Posts
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
}


3.级联删除

删除一个Blog对象后,对应的Post对象应该全部删除

Castle ActiveRecord学习实践(4):实现One-Many关系的映射[Test]
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
public void TestCascadingDelete()
Castle ActiveRecord学习实践(4):实现One-Many关系的映射
}


同样要注意设置级联操作。

关于One-Many关联映射就介绍这么多了,至于Many-One关联同One-Many,只不过对HasManyBlongsTo设置的位置不一样而已,在下一篇文章中我会介绍在ActiveRecord中实现Many-Many关联映射。

 

参考资料

Castle的官方网站http://www.castleproject.org

相关文章: