Castle ActiveRecord学习实践
2010-12-02 13:48
405 查看
实现One-Many
这里我采用上篇中将过(的)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 |
类型 | 说明 |
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
08-16基于Castle ActiveRecord开发Domain Model详解(一)对象关系到数据表的映射
CastleProject非常庞大,ActiveRecord是其中一个非常适合用于DomainModel开发的O/RMapping框架。它使用.NET的反射特性无需配置文件,集成NHibernate完成数据层持久化功[阅读全文]
08-09Castle ActiveRecord学习实践(9):使用ActiveRecord的一些技巧
主要内容 1.由实体类生成数据表 2.运行存在的SQL脚本 3.使用空属类型 4.使用枚举类型的属性 5.使用NHibernate中的日志记录 一.由实体类生成数据表 在前面所用到的例子中我们都是先有数据表结构,然后才有实体类,然而这会让很多朋友[阅读全文]
08-09Castle ActiveRecord学习实践(7):使用HQL查询
主要内容 1.HQL概述 2.SimpleQuery查询 3.ScalarQuery查询 4.自定义查询 5.使用CallBack 一.HQL简单介绍 HQL全名是HibernateQueryLangua[阅读全文]
07-10Castle ActiveRecord学习实践(10):深度分析Schema Pitfals
摘要:写这篇文章缘于昨天跟Linkin的一段聊天。我在使用ActiveRecord的一些技巧一文中的由实体类生成数据库表提到了这样一句话:生成数据库表时只有当该表不存在时ActiveRecord才会生成,否则表如果存在ActiveRecord不会做任何事情,也[阅读全文]
07-10Castle ActiveRecord学习实践(8):数据有效性的验证
主要内容 1.概述 2.使用Validation 3.如何扩展 4.深入分析验证 一.概述 在录入数据时,对数据有效性的验证是必不可少的,很多时候我们在UI层上就会做一层验证,但有时也需要在底层做一些必要的处理[阅读全文]
07-10Castle ActiveRecord学习实践(6):延迟加载和使用Where子句
摘要:在ActiveRecord中把数据库表之间的关联关系采用对象间的聚合关系来表现,然而这却带来一系列的性能上的问题。就像我在One-Many中用到的例子Blog,使用Blog.Find(1)查找了一个Blog对象,也许[阅读全文]
07-10Castle ActiveRecord学习实践(5):实现Many Many关系的映射
主要内容 1.准备数据库表 2.编写实体类 3.编写测试代码 一.准备数据库表 接着在上篇文章中的例子,为了实现多对多的关系,我们引入Community,即每个Blog可以属于多个社区,每个社区也可以有多个Blog。CREATETABLEBlog[阅读全文]
07-10Castle ActiveRecord学习实践(4):实现One-Many关系的映射
主要内容 1.准备数据表结构 2.编写实体类并介绍HasMany和BlongsTo特性 3.构建配置信息 4.编写测试代码 一.准备数据表结构 在这个例子中,我们引入了两个对象Blog、Post,它们之间的关系是一对多,即一个Blog有多篇Post[阅读全文]
07-02Castle ActiveRecord学习实践(3):映射基础
主要内容 简单映射 1.ActiveRecordAttribute 2.PrimaryKeyAttribute 3.CompositeKeyAttribute 4.PropertyAttribute 5.FieldAttribute 一.Act[阅读全文]
07-02Castle ActiveRecord学习实践(2):构建配置信息
主要内容 1.需要配置什么 2.如何去配置 3.常见的配置示例 一.需要配置什么 在第一篇大家都已经看到了,其实我们的配置信息跟用NHibernate时的配置是一样的,这是因为ActiveRecord在底层封装了NHibernate。为了没有用过NH[阅读全文]
07-02Castle ActiveRecord学习实践:快速入门指南
摘要:最近几天有时间看了一下Castle,原来它的功能是如此的强大,从数据访问框架到IOC容器,再到WEB框架,基本包括了整个开发过程中的所有东西,看来得好好学习研究一下了,并且打算把自己学习过程的一些东西记录下来。先从A[阅读全文]
相关文章推荐
- Castle ActiveRecord学习实践(1):快速入门指南
- Castle ActiveRecord学习实践(1):快速入门指南
- Castle ActiveRecord学习实践(12)——对象状态
- Castle ActiveRecord学习实践(9):使用ActiveRecord的一些技巧
- Castle ActiveRecord学习实践(4)关系映射
- Castle ActiveRecord学习实践(11)——ActiveRecordMediator
- Castle ActiveRecord学习实践(1):快速入门指南
- Castle ActiveRecord学习实践(10):深度分析Schema Pitfals
- Castle ActiveRecord学习实践(2):构建配置信息
- Castle ActiveRecord学习实践(1):快速入门指南
- Castle ActiveRecord学习实践4---转
- Castle ActiveRecord学习实践
- Castle ActiveRecord学习实践(7)级联
- Castle ActiveRecord学习实践(2):构建配置信息
- Castle ActiveRecord学习实践(1)入门
- Castle ActiveRecord学习实践(1):映射基础
- C#.Net Castle ActiveRecord学习实践(9):使用ActiveRecord的一些技巧
- Castle ActiveRecord学习实践(1):快速入门指南
- Castle ActiveRecord学习实践(8)HQL查询
- Castle ActiveRecord学习实践(10):深度分析Schema Pitfals