这里我采用上篇中将过(的)XML配置方式
<?xml version="1.0" encoding="utf-8" ?>
<activerecord>
<config>
<add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
<add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
<add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
<add key="hibernate.connection.connection_string" value="Data Source=.;Initial Catalog=test;Integrated Security=SSPI" />
</config>
</activerecord>
四.编写测试代码
1.级联增加:新增一个Blog,并同时添加相关(的)Post到数据表中
[Test]
public void TestCascadingSave()
{
//创建Blog对象
Blog blog = new Blog();
blog.Name="Terrylee's Tech Space";
blog.Author = "Terrylee";
//执行事务,持久化对象到数据库
using(TransactionScope tran = new TransactionScope())
{
try
{
blog.Create();
for(int i=1;i<11;i++)
{
//创建Post对象
Post post = new Post();
post.Title="This is my "+i.ToString()+" post";
post.Category="Castle";
post.Blog = blog;
post.Save();
}
tran.VoteCommit();
}
catch
{
tran.VoteRollBack();
}
}// The changes will be sent to the DB when the session is disposed here
}
2.级联更新:
首先我们为一个已经存在(的)Blog增加多个Post
[Test]
public void TestCascadingUpdate()
{
//找到ID为5(的)Blog
Blog blog = Blog.Find(5);
//执行事务,持久化对象到数据库
using(TransactionScope tran = new TransactionScope())
{
try
{
for(int i=1;i<5;i++)
{
//创建Post对象
Post post = new Post();
post.Title="This is my "+i.ToString()+" post";
post.Category="Castle";
post.Save();
//注意这句
blog.Posts.Add(post);
}
blog.Update();
tran.VoteCommit();
}
catch
{
tran.VoteRollBack();
}
}
}
当然上面(的)更新代码(也)可以这样去写:
[Test]
public void TestCascadingUpdate()
{
//找到ID为5(的)Blog
Blog blog = Blog.Find(5);
//执行事务,持久化对象到数据库
using(TransactionScope tran = new TransactionScope())
{
try
{
for(int i=1;i<5;i++)
{
//创建Post对象
Post post = new Post();
post.Title="This is my "+i.ToString()+" post";
post.Category="Castle";
//在这儿指定它们(的)关联
post.Blog = blog;
post.Save();
}
tran.VoteCommit();
}
catch
{
tran.VoteRollBack();
}
}
}
但(是)如果我们去掉post.Save()这句话,(就)会发现Post并没有增加到库中:
[Test]
public void TestCascadingUpdate()
{
//找到ID为5(的)Blog
Blog blog = Blog.Find(5);
//执行事务,持久化对象到数据库
using(TransactionScope tran = new TransactionScope())
{
try
{
for(int i=1;i<5;i++)
{
//创建Post对象
Post post = new Post();
post.Title="This is my "+i.ToString()+" post";
post.Category="Castle";
//注释掉这句
//post.Save();
blog.Posts.Add(post);
}
blog.Update();
tran.VoteCommit();
}
catch
{
tran.VoteRollBack();
}
}
}
此时,必须修改我们(的)Blog类,设置级联操作为SaveUpdate,上面(的)代码才可以正常执行
//
[HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid",Cascade=ManyRelationCascadeEnum.SaveUpdate)]
public IList Posts
{
get { return _posts; }
set { _posts = value; }
}
下面再测试一个删除某一个Blog(的)某些Post后,再保存
[Test]
public void TestCascadingUpdateDel()
{
//找到ID为7(的)Blog
Blog blog = Blog.Find(7);
int expectedCount = blog.Posts.Count;
using(TransactionScope tran = new TransactionScope())
{
try
{
blog.Posts.RemoveAt(0);
blog.Update();
tran.VoteCommit();
}
catch
{
tran.VoteRollBack();
}
}
int actualCount = Blog.Find(7).Posts.Count;
Assert.AreEqual(expectedCount-1,actualCount);
}
上面这段代码测试可以通过,但(是)我们会发现表Posts中会有一些记录没有BlogId,修改Blog实体类重新设置级联操作,(就)可以正常删除了:
//
[HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid",Cascade=ManyRelationCascadeEnum.AllDeleteOrphan)]
public IList Posts
{
get { return _posts; }
set { _posts = value; }
}
3.级联删除
删除一个Blog对象后,对应(的)Post对象应该全部删除
[Test]
public void TestCascadingDelete()
{
//找到ID为7(的)Blog对象
Blog blog = Blog.Find(5);
using(TransactionScope tran = new TransactionScope())
{
try
{
blog.Delete();
tran.VoteCommit();
}
catch
{
tran.VoteRollBack();
}
}
}
同样要注意设置级联操作。
关于One-Many关联映射(就)介绍这么多了,至于Many-One关联同One-Many,只不过对HasMany和BlongsTo设置(的)位置不一样而已,在下一篇文章中我会介绍在ActiveRecord中实现Many-Many关联映射。
实现Many Many
主要内容
1.准备数据库表
2.编写实体类
3.编写测试代码
一.准备数据库表
接着在上篇文章中(的)例子,为了实现多对多(的)关系,我们引入Community,即每个Blog可以属于多个社区,每个社区(也)可以有多个Blog。
CREATE TABLE Blogs (
blog_id int IDENTITY(1, 1) PRIMARY KEY,
blog_name varchar(50),
blog_author varchar(50)
)
CREATE TABLE Blog_Community (
blog_Id int NOT NULL ,
community_Id int NOT NULL
)
CREATE TABLE Communities (
community_Id int IDENTITY (1, 1) PRIMARY KEY,
community_Name varchar (50) ,
community_Intro varchar (500)
)
二.编写实体类代码
为了实现多对多(的)关系,我们要在Blog、Community类中分别使用HasAndBelongsToMany特性,不需要编写Blog_Community类。示例代码:
// Blog
[HasAndBelongsToMany( typeof(Community),
Table="Blog_Community",
ColumnRef=" community_id ",
ColumnKey=" blog_id " )]
public IList Communitys
{
get { return _community; }
set { _ community = value; }
}
// Community
[HasAndBelongsToMany( typeof(Blog),
Table="Blog_Community",
ColumnRef="blog_id",
ColumnKey="community_id" )]
public IList Blogs
{
get { return _blog; }
set { _ blog = value; }
}
HasAndBelongsToMany(的)参数相信大家都能够看明白,指定关联表名和关联(的)外键(就)可以了。
注意:这三个参数必须指定,不可以省略!
HasManyAttribute说明
属性 | 说明 | 示例 |
Cascade | 指明哪些操作会从父对象级联到关联(的)对象,相关(的)操作见后面,如果不指定,则为None | Cascade=ManyRelationCascadeEnum.All |
Inverse | 指定(是)否级联操作 | Inverse =true|false |
Schema | 指定Schema(的)名字 | Schema="ARDemo" |
Table | 指定持久化类所关联(的)数据库表名,如果表名与类名相同,可以省略 | Table="posts" |
ColumnKey | 本实体类于另一个实体类关联(的)外键 | ColumnKey="community_id" |
ColumnRef | 另一实体类(的)外键 | ColumnRef="blog_id" |
Where | 指定一个附加SQL(的)Where子句 | Where="IsPost = 0" |
Lazy | 指定(是)否延迟加载关联对象 | Lazy=true|false |
Cascade(的)类型值有如下几种
类型 | 说明 |
None | 不进行级联操作 |
SaveUpdate | 进行级联Save/Update操作 |
Delete | 进行级联Delete操作 |
All | 进行级联Save/Update/Delete操作 |
AllDeleteOrphan | 进行级联Save/Update/Delete操作,并删除无相关父对象(的)子对象 |
最后完整(的)实体类如下:
/**//// <summary>
/// Blog (的)摘要说明。
/// </summary>
[ActiveRecord("Blogs")]
public class Blog : ActiveRecordBase
{
private int _id;
private String _name;
private String _author;
private IList _community;
[PrimaryKey(PrimaryKeyType.Identity, "blog_id")]
public int Id
{
get { return _id; }
set { _id = value; }
}
[Property("blog_name")]
public String Name
{
get { return _name; }
set { _name = value; }
}
[Property("blog_author")]
public String Author
{
get { return _author; }
set { _author = value; }
}
[HasAndBelongsToMany(typeof(Community),
Table="Blog_Community",
ColumnRef=" community_id ",
ColumnKey=" blog_id " )]
public IList Communities
{
get { return _community; }
set { _community = value; }
}
public static void DeleteAll()
{
DeleteAll( typeof(Blog) );
}
public static Blog[] FindAll()
{
return (Blog[]) FindAll( typeof(Blog) );
}
public static Blog Find(int id)
{
return (Blog) FindByPrimaryKey( typeof(Blog), id );
}
}
/**//// <summary>
/// Community (的)摘要说明。
/// </summary>
[ActiveRecord("Communities")]
public class Community : ActiveRecordBase
{
private int _id;
private String _name;
private String _intro;
private IList _blog;
[PrimaryKey(PrimaryKeyType.Identity, "Community_Id")]
public int Id
{
get { return _id; }
set { _id = value; }
}
[Property("Community_Name")]
public String Name
{
get { return _name; }
set { _name = value; }
}
[Property("Community_Intro")]
public String Author
{
get { return _intro; }
set { _intro = value; }
}
[HasAndBelongsToMany(typeof(Blog),
Table="Blog_Community",
ColumnRef="blog_id",
ColumnKey="community_id" )]
public IList Blogs
{
get { return _blog; }
set { _blog = value; }
}
public static void DeleteAll()
{
DeleteAll( typeof(Community) );
}
public static Community[] FindAll()
{
return (Community[]) FindAll( typeof(Community) );
}
public static Community Find(int id)
{
return (Community) FindByPrimaryKey( typeof(Community), id );
}
}
三.编写测试代码
下面(是)我写(的)一些简单(的)测试代码,有兴趣(的)可以看一下。
1.级联增加:新增一个Blog,让它同时属于好几个社区
[Test]
public void TestCascadingSave()
{
//新建一个Blog
Blog blog = new Blog();
blog.Name = "Tech Space";
blog.Author = "Terrylee";
//属于ID为1,2社区
ArrayList list = new ArrayList();
list.Add(Community.Find(1));
list.Add(Community.Find(2));
blog.Communities = list;
//保存
blog.Save();
}
2.级联更新:对一个已经存在Blog,更改它属于更多(的)社区
[Test]
public void TestCascadingUpdate()
{
//测试1:查找一个Blog
Blog blog = Blog.Find(10);
IList clist = blog.Communities;
clist.Add(Community.Find(4));
clist.Add(Community.Find(3));
blog.Save();
//测试2:查找一个Community
Community community = Community.Find(3);
IList blist = community.Blogs;
blist.Add(Blog.Find(8));
community.Save();
}
3.级联删除:删除一个Blog,级联表中对应(的)记录应该删除,但Community不能删除,因为还有别(的)Blog和它关联
[Test]
public void TestCascadingDelete()
{
//测试1:删除Blog
Blog blog = Blog.Find(10);
using(TransactionScope btran = new TransactionScope())
{
try
{
blog.Delete();
btran.VoteCommit();
}
catch
{
btran.VoteRollBack();
}
}
//测试2:删除Community
Community community = Community.Find(3);
using(TransactionScope ctran = new TransactionScope())
{
try
{
community.Delete();
ctran.VoteCommit();
}
catch
{
ctran.VoteRollBack();
}
}
}
好了,关于Many-Many关联映射(就)写这么多了,内容比较简单。下篇文章我会介绍在ActiveRecord中实现延迟加载和使用Where子句。
http://www.qzsou.cn/aWangLuo/aAspNet/47823.html
http://www.qzsou.cn/Search.asp?searchtype=-1&searchword=Castle+ActiveRecord