Castle ActiveRecord学习实践(4):实现One-Many关系的映射 - TerryLee‘s Tech Space - 博客园
来源:百度文库 编辑:神马文学网 时间:2024/04/27 13:31:44
中的基本映射以及构建配置信息,本文我们用ActiveRecord里面的Blog,Post例子来实现One-Many/Many-One关联。
主要内容
1.准备数据表结构
2.编写实体类并介绍HasMany和BlongsTo特性
3.构建配置信息
4.编写测试代码
一.准备数据表结构
在这个例子中,我们引入了两个对象Blog、Post,它们之间的关系是一对多,即一个Blog有多篇Post。需要用到的数据表结构如下
CREATE TABLE Blogs (
blog_id int IDENTITY(1, 1) PRIMARY KEY,
blog_name varchar(50),
blog_author varchar(50)
)
CREATE TABLE Posts (
post_id int IDENTITY(1, 1) PRIMARY KEY,
post_title varchar(50),
post_contents text,
post_categories varchar(50),
post_blogid int FOREIGN KEY REFERENCES Blogs (blog_id),
post_created datetime,
post_published bit
)
二.编写实体类
首先我们来看Blog实体类的编写,需要用到HasMany特性,这时我们会在Blog实体类中定义一个Posts属性,用它来表示该Blog所发表的所有Posts,代码如下
[ActiveRecord("Blogs")]
public class Blog : ActiveRecordBase
{
//……
private IList _posts;
[HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid")]
public IList Posts
{
get { return _posts; }
set { _posts = value; }
}
}
HasManyAttribute说明
属性
说明
示例
Cascade
指明哪些操作会从父对象级联到关联的对象,相关的操作见后面,如果不指定,则为None
Cascade=ManyRelationCascadeEnum.All
Inverse
指定是否级联操作
Inverse =true|false
Schema
指定Schema的名字
Schema="ARDemo"
Table
指定持久化类所关联的数据库表名,如果表名与类名相同,可以省略
Table="posts"
ColumnKey
指定关联类的一个属性,这个属性将会和本外键相对应。
ColumnKey="post_blogid"
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操作,并删除无相关父对象的子对象
在Post实体类中,我们需要定义一个Blog类型的属性,并且用到BlongsTo特性,即一个Post属于某一个Blog,代码如下:
[ActiveRecord("Posts")]
public class Post : ActiveRecordBase
{
//……
private Blog _blog;
[BelongsTo("blogid")]
public Blog Blog
{
get { return _blog; }
set { _blog = value; }
}
}
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选项有三个:Auto,True,False
最后完整的Blog实体类如下
/**////
/// Blog 的摘要说明。
///
[ActiveRecord("Blogs")]
public class Blog : ActiveRecordBase
{
private int _id;
private String _name;
private String _author;
private IList _posts;
[PrimaryKey(PrimaryKeyType.Native, "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; }
}
[HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid")]
public IList Posts
{
get { return _posts; }
set { _posts = 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 );
}
}
完整的Post类如下
/**////
/// Post 的摘要说明。
///
[ActiveRecord("Posts")]
public class Post : ActiveRecordBase
{
private int _id;
private String _title;
private String _contents;
private String _category;
private DateTime _created;
private bool _published;
private Blog _blog;
public Post()
{
_created = DateTime.Now;
}
public Post(Blog blog, String title, String contents, String category) : this()
{
_blog = blog;
_title = title;
_contents = contents;
_category = category;
}
[PrimaryKey(PrimaryKeyType.Native,"post_id")]
public int Id
{
get { return _id; }
set { _id = value; }
}
[Property("post_title")]
public String Title
{
get { return _title; }
set { _title = value; }
}
[Property(Column="post_contents",ColumnType="StringClob")]
public String Contents
{
get { return _contents; }
set { _contents = value; }
}
[Property("post_categories")]
public String Category
{
get { return _category; }
set { _category = value; }
}
[BelongsTo("post_blogid")]
public Blog Blog
{
get { return _blog; }
set { _blog = value; }
}
[Property("post_created")]
public DateTime Created
{
get { return _created; }
set { _created = value; }
}
[Property("post_published")]
public bool Published
{
get { return _published; }
set { _published = value; }
}
public static void DeleteAll()
{
ActiveRecordBase.DeleteAll( typeof(Post) );
}
public static Post[] FindAll()
{
return (Post[]) ActiveRecordBase.FindAll( typeof(Post) );
}
}
三.构建配置信息
这里我采用上篇中将过的XML配置方式
四.编写测试代码
1.级联增加:新增一个Blog,并同时添加相关的Post到数据表中
[Test]
public void TestCascadingSave()
360docimg_501_{
360docimg_502_
360docimg_503_ //创建Blog对象
360docimg_504_
360docimg_505_ Blog blog = new Blog();
360docimg_506_
360docimg_507_ blog.Name="Terrylee‘s Tech Space";
360docimg_508_
360docimg_509_ blog.Author = "Terrylee";
360docimg_510_
360docimg_511_
360docimg_512_
360docimg_513_ //执行事务,持久化对象到数据库
360docimg_514_
360docimg_515_ using(TransactionScope tran = new TransactionScope())
360docimg_516_
360docimg_517_360docimg_518_ 360docimg_519_{
360docimg_520_
360docimg_521_ try
360docimg_522_
360docimg_523_360docimg_524_ 360docimg_525_{
360docimg_526_
360docimg_527_ blog.Create();
360docimg_528_
360docimg_529_
360docimg_530_
360docimg_531_ for(int i=1;i<11;i++)
360docimg_532_
360docimg_533_360docimg_534_ 360docimg_535_{
360docimg_536_
360docimg_537_ //创建Post对象
360docimg_538_
360docimg_539_ Post post = new Post();
360docimg_540_
360docimg_541_ post.Title="This is my "+i.ToString()+" post";
360docimg_542_
360docimg_543_ post.Category="Castle";
360docimg_544_
360docimg_545_ post.Blog = blog;
360docimg_546_
360docimg_547_ post.Save();
360docimg_548_
360docimg_549_ }
360docimg_550_
360docimg_551_
360docimg_552_
360docimg_553_ tran.VoteCommit();
360docimg_554_
360docimg_555_ }
360docimg_556_
360docimg_557_ catch
360docimg_558_
360docimg_559_360docimg_560_ 360docimg_561_{
360docimg_562_
360docimg_563_ tran.VoteRollBack();
360docimg_564_
360docimg_565_ }
360docimg_566_
360docimg_567_ }// The changes will be sent to the DB when the session is disposed here
360docimg_568_
360docimg_569_}
2.级联更新:
首先我们为一个已经存在的Blog增加多个Post
360docimg_570_[Test]
360docimg_571_
360docimg_572_public void TestCascadingUpdate()
360docimg_573_
360docimg_574_360docimg_575_360docimg_576_{
360docimg_577_
360docimg_578_ //找到ID为5的Blog
360docimg_579_
360docimg_580_ Blog blog = Blog.Find(5);
360docimg_581_
360docimg_582_
360docimg_583_
360docimg_584_ //执行事务,持久化对象到数据库
360docimg_585_
360docimg_586_ using(TransactionScope tran = new TransactionScope())
360docimg_587_
360docimg_588_360docimg_589_ 360docimg_590_{
360docimg_591_
360docimg_592_ try
360docimg_593_
360docimg_594_360docimg_595_ 360docimg_596_{
360docimg_597_
360docimg_598_ for(int i=1;i<5;i++)
360docimg_599_
360docimg_600_360docimg_601_ 360docimg_602_{
360docimg_603_
360docimg_604_ //创建Post对象
360docimg_605_
360docimg_606_ Post post = new Post();
360docimg_607_
360docimg_608_ post.Title="This is my "+i.ToString()+" post";
360docimg_609_
360docimg_610_ post.Category="Castle";
360docimg_611_
360docimg_612_
360docimg_613_
360docimg_614_ post.Save();
360docimg_615_
360docimg_616_
360docimg_617_
360docimg_618_ //注意这句
360docimg_619_
360docimg_620_ blog.Posts.Add(post);
360docimg_621_
360docimg_622_ }
360docimg_623_
360docimg_624_
360docimg_625_
360docimg_626_ blog.Update();
360docimg_627_
360docimg_628_
360docimg_629_
360docimg_630_ tran.VoteCommit();
360docimg_631_
360docimg_632_ }
360docimg_633_
360docimg_634_ catch
360docimg_635_
360docimg_636_360docimg_637_ 360docimg_638_{
360docimg_639_
360docimg_640_ tran.VoteRollBack();
360docimg_641_
360docimg_642_ }
360docimg_643_
360docimg_644_ }
360docimg_645_
360docimg_646_}
当然上面的更新代码也可以这样去写:
360docimg_647_[Test]
360docimg_648_
360docimg_649_public void TestCascadingUpdate()
360docimg_650_
360docimg_651_360docimg_652_360docimg_653_{
360docimg_654_
360docimg_655_ //找到ID为5的Blog
360docimg_656_
360docimg_657_ Blog blog = Blog.Find(5);
360docimg_658_
360docimg_659_
360docimg_660_
360docimg_661_ //执行事务,持久化对象到数据库
360docimg_662_
360docimg_663_ using(TransactionScope tran = new TransactionScope())
360docimg_664_
360docimg_665_360docimg_666_ 360docimg_667_{
360docimg_668_
360docimg_669_ try
360docimg_670_
360docimg_671_360docimg_672_ 360docimg_673_{
360docimg_674_
360docimg_675_ for(int i=1;i<5;i++)
360docimg_676_
360docimg_677_360docimg_678_ 360docimg_679_{
360docimg_680_
360docimg_681_ //创建Post对象
360docimg_682_
360docimg_683_ Post post = new Post();
360docimg_684_
360docimg_685_ post.Title="This is my "+i.ToString()+" post";
360docimg_686_
360docimg_687_ post.Category="Castle";
360docimg_688_
360docimg_689_
360docimg_690_
360docimg_691_ //在这儿指定它们的关联
360docimg_692_
360docimg_693_ post.Blog = blog;
360docimg_694_
360docimg_695_ post.Save();
360docimg_696_
360docimg_697_ }
360docimg_698_
360docimg_699_
360docimg_700_
360docimg_701_ tran.VoteCommit();
360docimg_702_
360docimg_703_ }
360docimg_704_
360docimg_705_ catch
360docimg_706_
360docimg_707_360docimg_708_ 360docimg_709_{
360docimg_710_
360docimg_711_ tran.VoteRollBack();
360docimg_712_
360docimg_713_ }
360docimg_714_
360docimg_715_ }
360docimg_716_
360docimg_717_}
但是如果我们去掉post.Save()这句话,就会发现Post并没有增加到库中:
360docimg_718_[Test]
360docimg_719_
360docimg_720_public void TestCascadingUpdate()
360docimg_721_
360docimg_722_360docimg_723_360docimg_724_{
360docimg_725_
360docimg_726_ //找到ID为5的Blog
360docimg_727_
360docimg_728_ Blog blog = Blog.Find(5);
360docimg_729_
360docimg_730_
360docimg_731_
360docimg_732_ //执行事务,持久化对象到数据库
360docimg_733_
360docimg_734_ using(TransactionScope tran = new TransactionScope())
360docimg_735_
360docimg_736_360docimg_737_ 360docimg_738_{
360docimg_739_
360docimg_740_ try
360docimg_741_
360docimg_742_360docimg_743_ 360docimg_744_{
360docimg_745_
360docimg_746_ for(int i=1;i<5;i++)
360docimg_747_
360docimg_748_360docimg_749_ 360docimg_750_{
360docimg_751_
360docimg_752_ //创建Post对象
360docimg_753_
360docimg_754_ Post post = new Post();
360docimg_755_
360docimg_756_ post.Title="This is my "+i.ToString()+" post";
360docimg_757_
360docimg_758_ post.Category="Castle";
360docimg_759_
360docimg_760_
360docimg_761_
360docimg_762_ //注释掉这句
360docimg_763_
360docimg_764_ //post.Save();
360docimg_765_
360docimg_766_
360docimg_767_
360docimg_768_ blog.Posts.Add(post);
360docimg_769_
360docimg_770_ }
360docimg_771_
360docimg_772_
360docimg_773_
360docimg_774_ blog.Update();
360docimg_775_
360docimg_776_
360docimg_777_
360docimg_778_ tran.VoteCommit();
360docimg_779_
360docimg_780_ }
360docimg_781_
360docimg_782_ catch
360docimg_783_
360docimg_784_360docimg_785_ 360docimg_786_{
360docimg_787_
360docimg_788_ tran.VoteRollBack();
360docimg_789_
360docimg_790_ }
360docimg_791_
360docimg_792_ }
360docimg_793_
360docimg_794_}
此时,必须修改我们的Blog类,设置级联操作为SaveUpdate,上面的代码才可以正常执行
360docimg_795_// 360docimg_796_360docimg_797_
360docimg_798_
360docimg_799_[HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid",Cascade=ManyRelationCascadeEnum.SaveUpdate)]
360docimg_800_
360docimg_801_public IList Posts
360docimg_802_
360docimg_803_360docimg_804_360docimg_805_{
360docimg_806_
360docimg_807_360docimg_808_ get 360docimg_809_{ return _posts; }
360docimg_810_
360docimg_811_360docimg_812_ set 360docimg_813_{ _posts = value; }
360docimg_814_
360docimg_815_}
下面再测试一个删除某一个Blog的某些Post后,再保存
360docimg_816_[Test]
360docimg_817_
360docimg_818_public void TestCascadingUpdateDel()
360docimg_819_
360docimg_820_360docimg_821_360docimg_822_{
360docimg_823_
360docimg_824_ //找到ID为7的Blog
360docimg_825_
360docimg_826_ Blog blog = Blog.Find(7);
360docimg_827_
360docimg_828_ int expectedCount = blog.Posts.Count;
360docimg_829_
360docimg_830_
360docimg_831_
360docimg_832_ using(TransactionScope tran = new TransactionScope())
360docimg_833_
360docimg_834_360docimg_835_ 360docimg_836_{
360docimg_837_
360docimg_838_ try
360docimg_839_
360docimg_840_360docimg_841_ 360docimg_842_{
360docimg_843_
360docimg_844_ blog.Posts.RemoveAt(0);
360docimg_845_
360docimg_846_
360docimg_847_
360docimg_848_ blog.Update();
360docimg_849_
360docimg_850_
360docimg_851_
360docimg_852_ tran.VoteCommit();
360docimg_853_
360docimg_854_ }
360docimg_855_
360docimg_856_ catch
360docimg_857_
360docimg_858_360docimg_859_ 360docimg_860_{
360docimg_861_
360docimg_862_ tran.VoteRollBack();
360docimg_863_
360docimg_864_ }
360docimg_865_
360docimg_866_ }
360docimg_867_
360docimg_868_
360docimg_869_
360docimg_870_ int actualCount = Blog.Find(7).Posts.Count;
360docimg_871_
360docimg_872_
360docimg_873_
360docimg_874_ Assert.AreEqual(expectedCount-1,actualCount);
360docimg_875_
360docimg_876_}
上面这段代码测试可以通过,但是我们会发现表Posts中会有一些记录没有BlogId,修改Blog实体类重新设置级联操作,就可以正常删除了:
360docimg_877_// 360docimg_878_360docimg_879_
360docimg_880_
360docimg_881_[HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid",Cascade=ManyRelationCascadeEnum.AllDeleteOrphan)]
360docimg_882_
360docimg_883_public IList Posts
360docimg_884_
360docimg_885_360docimg_886_360docimg_887_{
360docimg_888_
360docimg_889_360docimg_890_ get 360docimg_891_{ return _posts; }
360docimg_892_
360docimg_893_360docimg_894_ set 360docimg_895_{ _posts = value; }
360docimg_896_
360docimg_897_}
3.级联删除
删除一个Blog对象后,对应的Post对象应该全部删除
360docimg_898_[Test]
360docimg_899_
360docimg_900_public void TestCascadingDelete()
360docimg_901_
360docimg_902_360docimg_903_360docimg_904_{
360docimg_905_
360docimg_906_ //找到ID为7的Blog对象
360docimg_907_
360docimg_908_ Blog blog = Blog.Find(5);
360docimg_909_
360docimg_910_
360docimg_911_
360docimg_912_ using(TransactionScope tran = new TransactionScope())
360docimg_913_
360docimg_914_360docimg_915_ 360docimg_916_{
360docimg_917_
360docimg_918_ try
360docimg_919_
360docimg_920_360docimg_921_ 360docimg_922_{
360docimg_923_
360docimg_924_ blog.Delete();
360docimg_925_
360docimg_926_
360docimg_927_
360docimg_928_ tran.VoteCommit();
360docimg_929_
360docimg_930_ }
360docimg_931_
360docimg_932_ catch
360docimg_933_
360docimg_934_360docimg_935_ 360docimg_936_{
360docimg_937_
360docimg_938_ tran.VoteRollBack();
360docimg_939_
360docimg_940_ }
360docimg_941_
360docimg_942_ }
360docimg_943_
360docimg_944_}
同样要注意设置级联操作。
关于One-Many关联映射就介绍这么多了,至于Many-One关联同One-Many,只不过对HasMany和BlongsTo设置的位置不一样而已,在下一篇文章中我会介绍在ActiveRecord中实现Many-Many关联映射。
参考资料
Castle的官方网站http://www.castleproject.org
posted on 2006-04-06 16:28TerryLee 阅读(3020)评论(37) 编辑 收藏引用收藏至365Key 所属分类:I O/R Mapping 、E Castle系列
360pskdocImg_945
主要内容
1.准备数据表结构
2.编写实体类并介绍HasMany和BlongsTo特性
3.构建配置信息
4.编写测试代码
一.准备数据表结构
在这个例子中,我们引入了两个对象Blog、Post,它们之间的关系是一对多,即一个Blog有多篇Post。需要用到的数据表结构如下
CREATE TABLE Blogs (
blog_id int IDENTITY(1, 1) PRIMARY KEY,
blog_name varchar(50),
blog_author varchar(50)
)
CREATE TABLE Posts (
post_id int IDENTITY(1, 1) PRIMARY KEY,
post_title varchar(50),
post_contents text,
post_categories varchar(50),
post_blogid int FOREIGN KEY REFERENCES Blogs (blog_id),
post_created datetime,
post_published bit
)
二.编写实体类
首先我们来看Blog实体类的编写,需要用到HasMany特性,这时我们会在Blog实体类中定义一个Posts属性,用它来表示该Blog所发表的所有Posts,代码如下
[ActiveRecord("Blogs")]
public class Blog : ActiveRecordBase
{
//……
private IList _posts;
[HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid")]
public IList Posts
{
get { return _posts; }
set { _posts = value; }
}
}
HasManyAttribute说明
属性
说明
示例
Cascade
指明哪些操作会从父对象级联到关联的对象,相关的操作见后面,如果不指定,则为None
Cascade=ManyRelationCascadeEnum.All
Inverse
指定是否级联操作
Inverse =true|false
Schema
指定Schema的名字
Schema="ARDemo"
Table
指定持久化类所关联的数据库表名,如果表名与类名相同,可以省略
Table="posts"
ColumnKey
指定关联类的一个属性,这个属性将会和本外键相对应。
ColumnKey="post_blogid"
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操作,并删除无相关父对象的子对象
在Post实体类中,我们需要定义一个Blog类型的属性,并且用到BlongsTo特性,即一个Post属于某一个Blog,代码如下:
[ActiveRecord("Posts")]
public class Post : ActiveRecordBase
{
//……
private Blog _blog;
[BelongsTo("blogid")]
public Blog Blog
{
get { return _blog; }
set { _blog = value; }
}
}
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选项有三个:Auto,True,False
最后完整的Blog实体类如下
/**////
/// Blog 的摘要说明。
///
[ActiveRecord("Blogs")]
public class Blog : ActiveRecordBase
{
private int _id;
private String _name;
private String _author;
private IList _posts;
[PrimaryKey(PrimaryKeyType.Native, "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; }
}
[HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid")]
public IList Posts
{
get { return _posts; }
set { _posts = 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 );
}
}
完整的Post类如下
/**////
/// Post 的摘要说明。
///
[ActiveRecord("Posts")]
public class Post : ActiveRecordBase
{
private int _id;
private String _title;
private String _contents;
private String _category;
private DateTime _created;
private bool _published;
private Blog _blog;
public Post()
{
_created = DateTime.Now;
}
public Post(Blog blog, String title, String contents, String category) : this()
{
_blog = blog;
_title = title;
_contents = contents;
_category = category;
}
[PrimaryKey(PrimaryKeyType.Native,"post_id")]
public int Id
{
get { return _id; }
set { _id = value; }
}
[Property("post_title")]
public String Title
{
get { return _title; }
set { _title = value; }
}
[Property(Column="post_contents",ColumnType="StringClob")]
public String Contents
{
get { return _contents; }
set { _contents = value; }
}
[Property("post_categories")]
public String Category
{
get { return _category; }
set { _category = value; }
}
[BelongsTo("post_blogid")]
public Blog Blog
{
get { return _blog; }
set { _blog = value; }
}
[Property("post_created")]
public DateTime Created
{
get { return _created; }
set { _created = value; }
}
[Property("post_published")]
public bool Published
{
get { return _published; }
set { _published = value; }
}
public static void DeleteAll()
{
ActiveRecordBase.DeleteAll( typeof(Post) );
}
public static Post[] FindAll()
{
return (Post[]) ActiveRecordBase.FindAll( typeof(Post) );
}
}
三.构建配置信息
这里我采用上篇中将过的XML配置方式
四.编写测试代码
1.级联增加:新增一个Blog,并同时添加相关的Post到数据表中
[Test]
public void TestCascadingSave()
360docimg_501_{
360docimg_502_
360docimg_503_ //创建Blog对象
360docimg_504_
360docimg_505_ Blog blog = new Blog();
360docimg_506_
360docimg_507_ blog.Name="Terrylee‘s Tech Space";
360docimg_508_
360docimg_509_ blog.Author = "Terrylee";
360docimg_510_
360docimg_511_
360docimg_512_
360docimg_513_ //执行事务,持久化对象到数据库
360docimg_514_
360docimg_515_ using(TransactionScope tran = new TransactionScope())
360docimg_516_
360docimg_517_360docimg_518_ 360docimg_519_{
360docimg_520_
360docimg_521_ try
360docimg_522_
360docimg_523_360docimg_524_ 360docimg_525_{
360docimg_526_
360docimg_527_ blog.Create();
360docimg_528_
360docimg_529_
360docimg_530_
360docimg_531_ for(int i=1;i<11;i++)
360docimg_532_
360docimg_533_360docimg_534_ 360docimg_535_{
360docimg_536_
360docimg_537_ //创建Post对象
360docimg_538_
360docimg_539_ Post post = new Post();
360docimg_540_
360docimg_541_ post.Title="This is my "+i.ToString()+" post";
360docimg_542_
360docimg_543_ post.Category="Castle";
360docimg_544_
360docimg_545_ post.Blog = blog;
360docimg_546_
360docimg_547_ post.Save();
360docimg_548_
360docimg_549_ }
360docimg_550_
360docimg_551_
360docimg_552_
360docimg_553_ tran.VoteCommit();
360docimg_554_
360docimg_555_ }
360docimg_556_
360docimg_557_ catch
360docimg_558_
360docimg_559_360docimg_560_ 360docimg_561_{
360docimg_562_
360docimg_563_ tran.VoteRollBack();
360docimg_564_
360docimg_565_ }
360docimg_566_
360docimg_567_ }// The changes will be sent to the DB when the session is disposed here
360docimg_568_
360docimg_569_}
2.级联更新:
首先我们为一个已经存在的Blog增加多个Post
360docimg_570_[Test]
360docimg_571_
360docimg_572_public void TestCascadingUpdate()
360docimg_573_
360docimg_574_360docimg_575_360docimg_576_{
360docimg_577_
360docimg_578_ //找到ID为5的Blog
360docimg_579_
360docimg_580_ Blog blog = Blog.Find(5);
360docimg_581_
360docimg_582_
360docimg_583_
360docimg_584_ //执行事务,持久化对象到数据库
360docimg_585_
360docimg_586_ using(TransactionScope tran = new TransactionScope())
360docimg_587_
360docimg_588_360docimg_589_ 360docimg_590_{
360docimg_591_
360docimg_592_ try
360docimg_593_
360docimg_594_360docimg_595_ 360docimg_596_{
360docimg_597_
360docimg_598_ for(int i=1;i<5;i++)
360docimg_599_
360docimg_600_360docimg_601_ 360docimg_602_{
360docimg_603_
360docimg_604_ //创建Post对象
360docimg_605_
360docimg_606_ Post post = new Post();
360docimg_607_
360docimg_608_ post.Title="This is my "+i.ToString()+" post";
360docimg_609_
360docimg_610_ post.Category="Castle";
360docimg_611_
360docimg_612_
360docimg_613_
360docimg_614_ post.Save();
360docimg_615_
360docimg_616_
360docimg_617_
360docimg_618_ //注意这句
360docimg_619_
360docimg_620_ blog.Posts.Add(post);
360docimg_621_
360docimg_622_ }
360docimg_623_
360docimg_624_
360docimg_625_
360docimg_626_ blog.Update();
360docimg_627_
360docimg_628_
360docimg_629_
360docimg_630_ tran.VoteCommit();
360docimg_631_
360docimg_632_ }
360docimg_633_
360docimg_634_ catch
360docimg_635_
360docimg_636_360docimg_637_ 360docimg_638_{
360docimg_639_
360docimg_640_ tran.VoteRollBack();
360docimg_641_
360docimg_642_ }
360docimg_643_
360docimg_644_ }
360docimg_645_
360docimg_646_}
当然上面的更新代码也可以这样去写:
360docimg_647_[Test]
360docimg_648_
360docimg_649_public void TestCascadingUpdate()
360docimg_650_
360docimg_651_360docimg_652_360docimg_653_{
360docimg_654_
360docimg_655_ //找到ID为5的Blog
360docimg_656_
360docimg_657_ Blog blog = Blog.Find(5);
360docimg_658_
360docimg_659_
360docimg_660_
360docimg_661_ //执行事务,持久化对象到数据库
360docimg_662_
360docimg_663_ using(TransactionScope tran = new TransactionScope())
360docimg_664_
360docimg_665_360docimg_666_ 360docimg_667_{
360docimg_668_
360docimg_669_ try
360docimg_670_
360docimg_671_360docimg_672_ 360docimg_673_{
360docimg_674_
360docimg_675_ for(int i=1;i<5;i++)
360docimg_676_
360docimg_677_360docimg_678_ 360docimg_679_{
360docimg_680_
360docimg_681_ //创建Post对象
360docimg_682_
360docimg_683_ Post post = new Post();
360docimg_684_
360docimg_685_ post.Title="This is my "+i.ToString()+" post";
360docimg_686_
360docimg_687_ post.Category="Castle";
360docimg_688_
360docimg_689_
360docimg_690_
360docimg_691_ //在这儿指定它们的关联
360docimg_692_
360docimg_693_ post.Blog = blog;
360docimg_694_
360docimg_695_ post.Save();
360docimg_696_
360docimg_697_ }
360docimg_698_
360docimg_699_
360docimg_700_
360docimg_701_ tran.VoteCommit();
360docimg_702_
360docimg_703_ }
360docimg_704_
360docimg_705_ catch
360docimg_706_
360docimg_707_360docimg_708_ 360docimg_709_{
360docimg_710_
360docimg_711_ tran.VoteRollBack();
360docimg_712_
360docimg_713_ }
360docimg_714_
360docimg_715_ }
360docimg_716_
360docimg_717_}
但是如果我们去掉post.Save()这句话,就会发现Post并没有增加到库中:
360docimg_718_[Test]
360docimg_719_
360docimg_720_public void TestCascadingUpdate()
360docimg_721_
360docimg_722_360docimg_723_360docimg_724_{
360docimg_725_
360docimg_726_ //找到ID为5的Blog
360docimg_727_
360docimg_728_ Blog blog = Blog.Find(5);
360docimg_729_
360docimg_730_
360docimg_731_
360docimg_732_ //执行事务,持久化对象到数据库
360docimg_733_
360docimg_734_ using(TransactionScope tran = new TransactionScope())
360docimg_735_
360docimg_736_360docimg_737_ 360docimg_738_{
360docimg_739_
360docimg_740_ try
360docimg_741_
360docimg_742_360docimg_743_ 360docimg_744_{
360docimg_745_
360docimg_746_ for(int i=1;i<5;i++)
360docimg_747_
360docimg_748_360docimg_749_ 360docimg_750_{
360docimg_751_
360docimg_752_ //创建Post对象
360docimg_753_
360docimg_754_ Post post = new Post();
360docimg_755_
360docimg_756_ post.Title="This is my "+i.ToString()+" post";
360docimg_757_
360docimg_758_ post.Category="Castle";
360docimg_759_
360docimg_760_
360docimg_761_
360docimg_762_ //注释掉这句
360docimg_763_
360docimg_764_ //post.Save();
360docimg_765_
360docimg_766_
360docimg_767_
360docimg_768_ blog.Posts.Add(post);
360docimg_769_
360docimg_770_ }
360docimg_771_
360docimg_772_
360docimg_773_
360docimg_774_ blog.Update();
360docimg_775_
360docimg_776_
360docimg_777_
360docimg_778_ tran.VoteCommit();
360docimg_779_
360docimg_780_ }
360docimg_781_
360docimg_782_ catch
360docimg_783_
360docimg_784_360docimg_785_ 360docimg_786_{
360docimg_787_
360docimg_788_ tran.VoteRollBack();
360docimg_789_
360docimg_790_ }
360docimg_791_
360docimg_792_ }
360docimg_793_
360docimg_794_}
此时,必须修改我们的Blog类,设置级联操作为SaveUpdate,上面的代码才可以正常执行
360docimg_795_// 360docimg_796_360docimg_797_
360docimg_798_
360docimg_799_[HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid",Cascade=ManyRelationCascadeEnum.SaveUpdate)]
360docimg_800_
360docimg_801_public IList Posts
360docimg_802_
360docimg_803_360docimg_804_360docimg_805_{
360docimg_806_
360docimg_807_360docimg_808_ get 360docimg_809_{ return _posts; }
360docimg_810_
360docimg_811_360docimg_812_ set 360docimg_813_{ _posts = value; }
360docimg_814_
360docimg_815_}
下面再测试一个删除某一个Blog的某些Post后,再保存
360docimg_816_[Test]
360docimg_817_
360docimg_818_public void TestCascadingUpdateDel()
360docimg_819_
360docimg_820_360docimg_821_360docimg_822_{
360docimg_823_
360docimg_824_ //找到ID为7的Blog
360docimg_825_
360docimg_826_ Blog blog = Blog.Find(7);
360docimg_827_
360docimg_828_ int expectedCount = blog.Posts.Count;
360docimg_829_
360docimg_830_
360docimg_831_
360docimg_832_ using(TransactionScope tran = new TransactionScope())
360docimg_833_
360docimg_834_360docimg_835_ 360docimg_836_{
360docimg_837_
360docimg_838_ try
360docimg_839_
360docimg_840_360docimg_841_ 360docimg_842_{
360docimg_843_
360docimg_844_ blog.Posts.RemoveAt(0);
360docimg_845_
360docimg_846_
360docimg_847_
360docimg_848_ blog.Update();
360docimg_849_
360docimg_850_
360docimg_851_
360docimg_852_ tran.VoteCommit();
360docimg_853_
360docimg_854_ }
360docimg_855_
360docimg_856_ catch
360docimg_857_
360docimg_858_360docimg_859_ 360docimg_860_{
360docimg_861_
360docimg_862_ tran.VoteRollBack();
360docimg_863_
360docimg_864_ }
360docimg_865_
360docimg_866_ }
360docimg_867_
360docimg_868_
360docimg_869_
360docimg_870_ int actualCount = Blog.Find(7).Posts.Count;
360docimg_871_
360docimg_872_
360docimg_873_
360docimg_874_ Assert.AreEqual(expectedCount-1,actualCount);
360docimg_875_
360docimg_876_}
上面这段代码测试可以通过,但是我们会发现表Posts中会有一些记录没有BlogId,修改Blog实体类重新设置级联操作,就可以正常删除了:
360docimg_877_// 360docimg_878_360docimg_879_
360docimg_880_
360docimg_881_[HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid",Cascade=ManyRelationCascadeEnum.AllDeleteOrphan)]
360docimg_882_
360docimg_883_public IList Posts
360docimg_884_
360docimg_885_360docimg_886_360docimg_887_{
360docimg_888_
360docimg_889_360docimg_890_ get 360docimg_891_{ return _posts; }
360docimg_892_
360docimg_893_360docimg_894_ set 360docimg_895_{ _posts = value; }
360docimg_896_
360docimg_897_}
3.级联删除
删除一个Blog对象后,对应的Post对象应该全部删除
360docimg_898_[Test]
360docimg_899_
360docimg_900_public void TestCascadingDelete()
360docimg_901_
360docimg_902_360docimg_903_360docimg_904_{
360docimg_905_
360docimg_906_ //找到ID为7的Blog对象
360docimg_907_
360docimg_908_ Blog blog = Blog.Find(5);
360docimg_909_
360docimg_910_
360docimg_911_
360docimg_912_ using(TransactionScope tran = new TransactionScope())
360docimg_913_
360docimg_914_360docimg_915_ 360docimg_916_{
360docimg_917_
360docimg_918_ try
360docimg_919_
360docimg_920_360docimg_921_ 360docimg_922_{
360docimg_923_
360docimg_924_ blog.Delete();
360docimg_925_
360docimg_926_
360docimg_927_
360docimg_928_ tran.VoteCommit();
360docimg_929_
360docimg_930_ }
360docimg_931_
360docimg_932_ catch
360docimg_933_
360docimg_934_360docimg_935_ 360docimg_936_{
360docimg_937_
360docimg_938_ tran.VoteRollBack();
360docimg_939_
360docimg_940_ }
360docimg_941_
360docimg_942_ }
360docimg_943_
360docimg_944_}
同样要注意设置级联操作。
关于One-Many关联映射就介绍这么多了,至于Many-One关联同One-Many,只不过对HasMany和BlongsTo设置的位置不一样而已,在下一篇文章中我会介绍在ActiveRecord中实现Many-Many关联映射。
参考资料
Castle的官方网站http://www.castleproject.org
posted on 2006-04-06 16:28TerryLee 阅读(3020)评论(37) 编辑 收藏引用收藏至365Key 所属分类:I O/R Mapping 、E Castle系列
360pskdocImg_945
Castle ActiveRecord学习实践(4):实现One-Many关系的映射 - TerryLee‘s Tech Space - 博客园
Castle IOC容器快速入门 - TerryLee‘s Tech Space - 博客...
博客园 - Terrylee‘s Tech Space - Enterprise Library2.0(1):Data Access Application Block学习
Castle IOC容器构建配置详解(一) - TerryLee‘s Tech Space...
数据库设计指南[整理] - Aero‘s Tech Space - 博客园
学习数学 - Bati's eHome of Tech - 博客园
Castle实践9-在Castle IOC容器中使用AspectSharp(全面剖析AspectSharp Facility) - 叶子的家 - 博客园
增加CCS1.1的Blog日志访问者记录功能 - Aero‘s Tech Space - ...
Hibernate 中多对多(many-to-many)关系的查询语句
消息映射的实现
SYS_CONNECT_BY_PATH 学习_zhwsh's space
SYS_CONNECT_BY_PATH 学习_zhwsh's space
博客园 - Terrylee的技术专栏 - 使用.NET Remoting开发分布式应用——配置文件篇
在Hibernate中实现复杂的数据映射--java学习资料
一个真正的豪宅,HOLW’S MOVING CASTLE, 图多有果
《Howl's Moving Castle》宫崎骏
《Howl's Moving Castle》宫崎骏
我的标签: Windows Mobile - AppleSeeker's Tech Blo...
Jajah - Tech is Amazing - 博客园
惠普V3704TX换成XP时蓝屏的解决方法[原创]_Wizard's Castle
对象关系映射ORM
解读ATL/WTL/MFC消息映射的实现方式
javascript实现类似google和msn space的拖拽(转载)
One Year's Later