castle One-Many/Many-One关联 --- 转

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

主要内容

1.准备数据表结构

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

3.构建配置信息

4.编写测试代码

 

一.准备数据表结构

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

None.gif CREATE   TABLE  Blogs (
None.gif
None.gif    blog_id     
int   IDENTITY ( 1 1 PRIMARY   KEY ,
None.gif
None.gif    blog_name   
varchar ( 50 ),
None.gif
None.gif    blog_author 
varchar ( 50 )
None.gif
None.gif)
None.gif
None.gif 
None.gif
None.gif
CREATE   TABLE  Posts (
None.gif
None.gif    post_id        
int   IDENTITY ( 1 1 PRIMARY   KEY ,
None.gif
None.gif    post_title     
varchar ( 50 ),
None.gif
None.gif    post_contents  
text ,
None.gif
None.gif    post_categories 
varchar ( 50 ),
None.gif
None.gif    post_blogid    
int   FOREIGN   KEY   REFERENCES  Blogs (blog_id),
None.gif
None.gif    post_created   
datetime ,
None.gif
None.gif    post_published 
bit
None.gif
None.gif)


二.编写实体类

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

 

None.gif [ActiveRecord( " Blogs " )]
None.gif
None.gif
public   class  Blog : ActiveRecordBase
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
//……
InBlock.gif

InBlock.gif    
private IList _posts;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [HasMany(
typeof(Post), Table="posts", ColumnKey="post_blogid")]
InBlock.gif
InBlock.gif    
public IList Posts
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _posts; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _posts = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}


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,代码如下:

None.gif [ActiveRecord( " Posts " )]
None.gif
None.gif
public   class  Post : ActiveRecordBase
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
//……
InBlock.gif

InBlock.gif    
private Blog _blog;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [BelongsTo(
"blogid")]
InBlock.gif
InBlock.gif    
public Blog Blog
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _blog; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _blog = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}


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实体类如下

ExpandedBlockStart.gif ContractedBlock.gif /**/ /// <summary>
InBlock.gif
InBlock.gif
/// Blog 的摘要说明。
InBlock.gif
ExpandedBlockEnd.gif
/// </summary>

None.gif
None.gif[ActiveRecord(
" Blogs " )]
None.gif
None.gif
public   class  Blog : ActiveRecordBase
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
private int _id;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
private String _name;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
private String _author;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
private IList _posts;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [PrimaryKey(PrimaryKeyType.Native, 
"blog_id")]
InBlock.gif
InBlock.gif    
public int Id
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _id; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _id = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [Property(
"blog_name")]
InBlock.gif
InBlock.gif    
public String Name
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _name; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _name = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [Property(
"blog_author")]
InBlock.gif
InBlock.gif    
public String Author
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _author; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _author = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
InBlock.gif
InBlock.gif    [HasMany(
typeof(Post), Table="posts", ColumnKey="post_blogid")]
InBlock.gif
InBlock.gif    
public IList Posts
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _posts; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _posts = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
public static void DeleteAll()
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        DeleteAll( 
typeof(Blog) );
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
public static Blog[] FindAll()
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
return (Blog[]) FindAll( typeof(Blog) );
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
public static Blog Find(int id)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
return (Blog) FindByPrimaryKey( typeof(Blog), id );
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

 

完整的Post类如下

None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**/ /// <summary>
InBlock.gif
InBlock.gif
/// Post 的摘要说明。
InBlock.gif
ExpandedBlockEnd.gif
/// </summary>

None.gif
None.gif[ActiveRecord(
" Posts " )]
None.gif
None.gif
public   class  Post : ActiveRecordBase
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
private int _id;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
private String _title;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
private String _contents;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
private String _category;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
private DateTime _created;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
private bool _published;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
private Blog _blog;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
public Post()
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        _created 
= DateTime.Now;
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
public Post(Blog blog, String title, String contents, String category) : this()
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        _blog 
= blog;
InBlock.gif
InBlock.gif        _title 
= title;
InBlock.gif
InBlock.gif        _contents 
= contents;
InBlock.gif
InBlock.gif        _category 
= category;
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [PrimaryKey(PrimaryKeyType.Native,
"post_id")]
InBlock.gif
InBlock.gif    
public int Id
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _id; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _id = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [Property(
"post_title")]
InBlock.gif
InBlock.gif    
public String Title
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _title; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _title = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [Property(Column
="post_contents",ColumnType="StringClob")]
InBlock.gif
InBlock.gif    
public String Contents
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _contents; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _contents = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [Property(
"post_categories")]
InBlock.gif
InBlock.gif    
public String Category
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _category; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _category = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [BelongsTo(
"post_blogid")]
InBlock.gif
InBlock.gif    
public Blog Blog
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _blog; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _blog = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [Property(
"post_created")]
InBlock.gif
InBlock.gif    
public DateTime Created
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _created; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _created = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [Property(
"post_published")]
InBlock.gif
InBlock.gif    
public bool Published
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _published; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _published = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
public static void DeleteAll()
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        ActiveRecordBase.DeleteAll( 
typeof(Post) );
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
public static Post[] FindAll()
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
return (Post[]) ActiveRecordBase.FindAll( typeof(Post) );
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}


三.构建配置信息

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

None.gif <? xml version="1.0" encoding="utf-8"  ?>
None.gif
None.gif
< activerecord >
None.gif
None.gif    
< config >
None.gif
None.gif        
< add  key ="hibernate.connection.driver_class"  value ="NHibernate.Driver.SqlClientDriver"   />
None.gif
None.gif        
< add  key ="hibernate.dialect"  value ="NHibernate.Dialect.MsSql2000Dialect"   />
None.gif
None.gif        
< add  key ="hibernate.connection.provider"  value ="NHibernate.Connection.DriverConnectionProvider"   />
None.gif
None.gif        
< add  key ="hibernate.connection.connection_string"  value ="Data Source=.;Initial Catalog=test;Integrated Security=SSPI"   />
None.gif
None.gif    
</ config >
None.gif
None.gif
</ activerecord >

 

四.编写测试代码

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

None.gif [Test]
None.gif
None.gif
public   void  TestCascadingSave()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
//创建Blog对象
InBlock.gif

InBlock.gif    Blog blog 
= new Blog();
InBlock.gif
InBlock.gif    blog.Name
="Terrylee's Tech Space";
InBlock.gif
InBlock.gif    blog.Author 
= "Terrylee";
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
//执行事务,持久化对象到数据库
InBlock.gif

InBlock.gif    
using(TransactionScope tran = new TransactionScope())
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
try
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            blog.Create();
InBlock.gif
InBlock.gif            
InBlock.gif
InBlock.gif            
for(int i=1;i<11;i++)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif
InBlock.gif                
//创建Post对象
InBlock.gif

InBlock.gif                Post post 
= new Post();
InBlock.gif
InBlock.gif                post.Title
="This is my "+i.ToString()+" post";
InBlock.gif
InBlock.gif                post.Category
="Castle";
InBlock.gif
InBlock.gif                post.Blog 
= blog;
InBlock.gif
InBlock.gif                post.Save();
InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif            tran.VoteCommit();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
catch
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            tran.VoteRollBack();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }
// The changes will be sent to the DB when the session is disposed here
InBlock.gif

ExpandedBlockEnd.gif}

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

 

None.gif [Test]
None.gif
None.gif
public   void  TestCascadingUpdate()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {   
InBlock.gif
InBlock.gif    
//找到ID为5的Blog
InBlock.gif

InBlock.gif    Blog blog 
= Blog.Find(5);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
//执行事务,持久化对象到数据库
InBlock.gif

InBlock.gif    
using(TransactionScope tran = new TransactionScope())
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
try
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{           
InBlock.gif
InBlock.gif            
for(int i=1;i<5;i++)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif
InBlock.gif                
//创建Post对象
InBlock.gif

InBlock.gif                Post post 
= new Post();
InBlock.gif
InBlock.gif                post.Title
="This is my "+i.ToString()+" post";
InBlock.gif
InBlock.gif                post.Category
="Castle";
InBlock.gif
InBlock.gif                
InBlock.gif
InBlock.gif                post.Save();
InBlock.gif
InBlock.gif                
InBlock.gif
InBlock.gif                
//注意这句
InBlock.gif

InBlock.gif                blog.Posts.Add(post);
InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
InBlock.gif
InBlock.gif            blog.Update();
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif            tran.VoteCommit();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
catch
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            tran.VoteRollBack();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}


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

None.gif [Test]
None.gif
None.gif
public   void  TestCascadingUpdate()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {   
InBlock.gif
InBlock.gif    
//找到ID为5的Blog
InBlock.gif

InBlock.gif    Blog blog 
= Blog.Find(5);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
//执行事务,持久化对象到数据库
InBlock.gif

InBlock.gif    
using(TransactionScope tran = new TransactionScope())
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
try
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{           
InBlock.gif
InBlock.gif            
for(int i=1;i<5;i++)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif
InBlock.gif                
//创建Post对象
InBlock.gif

InBlock.gif                Post post 
= new Post();
InBlock.gif
InBlock.gif                post.Title
="This is my "+i.ToString()+" post";
InBlock.gif
InBlock.gif                post.Category
="Castle";
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif                
//在这儿指定它们的关联
InBlock.gif

InBlock.gif                post.Blog 
= blog;
InBlock.gif
InBlock.gif                post.Save();
InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
InBlock.gif
InBlock.gif        tran.VoteCommit();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
catch
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            tran.VoteRollBack();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}


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

None.gif [Test]
None.gif
None.gif
public   void  TestCascadingUpdate()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {   
InBlock.gif
InBlock.gif    
//找到ID为5的Blog
InBlock.gif

InBlock.gif    Blog blog 
= Blog.Find(5);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
//执行事务,持久化对象到数据库
InBlock.gif

InBlock.gif    
using(TransactionScope tran = new TransactionScope())
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
try
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{           
InBlock.gif
InBlock.gif            
for(int i=1;i<5;i++)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif
InBlock.gif                
//创建Post对象
InBlock.gif

InBlock.gif                Post post 
= new Post();
InBlock.gif
InBlock.gif                post.Title
="This is my "+i.ToString()+" post";
InBlock.gif
InBlock.gif                post.Category
="Castle";
InBlock.gif
InBlock.gif                
InBlock.gif
InBlock.gif                
//注释掉这句
InBlock.gif
InBlock.gif                
//post.Save();
InBlock.gif

InBlock.gif                
InBlock.gif
InBlock.gif                blog.Posts.Add(post);
InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif            blog.Update();
InBlock.gif
InBlock.gif            
InBlock.gif
InBlock.gif        tran.VoteCommit();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
catch
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            tran.VoteRollBack();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}


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

None.gif //  dot.gifdot.gif
None.gif

None.gif[HasMany(
typeof (Post), Table = " posts " , ColumnKey = " post_blogid " ,Cascade = ManyRelationCascadeEnum.SaveUpdate)]
None.gif
None.gif
public  IList Posts
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
get dot.gifreturn _posts; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
set dot.gif{ _posts = value; }
InBlock.gif
ExpandedBlockEnd.gif}


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

None.gif [Test]
None.gif
None.gif
public   void  TestCascadingUpdateDel()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {   
InBlock.gif
InBlock.gif    
//找到ID为7的Blog
InBlock.gif

InBlock.gif    Blog blog 
= Blog.Find(7);
InBlock.gif
InBlock.gif    
int expectedCount = blog.Posts.Count;
InBlock.gif
InBlock.gif    
InBlock.gif
InBlock.gif    
using(TransactionScope tran = new TransactionScope())
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
try
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            blog.Posts.RemoveAt(
0);
InBlock.gif
InBlock.gif            
InBlock.gif
InBlock.gif            blog.Update();
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif            tran.VoteCommit();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
catch
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            tran.VoteRollBack();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
InBlock.gif
InBlock.gif    
int actualCount = Blog.Find(7).Posts.Count;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    Assert.AreEqual(expectedCount
-1,actualCount);
InBlock.gif
ExpandedBlockEnd.gif}


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

None.gif //  dot.gifdot.gif
None.gif

None.gif[HasMany(
typeof (Post), Table = " posts " , ColumnKey = " post_blogid " ,Cascade = ManyRelationCascadeEnum.AllDeleteOrphan)]
None.gif
None.gif
public  IList Posts
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
get dot.gifreturn _posts; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
set dot.gif{ _posts = value; }
InBlock.gif
ExpandedBlockEnd.gif}


3.级联删除

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

None.gif [Test]
None.gif
None.gif
public   void  TestCascadingDelete()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
//找到ID为7的Blog对象
InBlock.gif

InBlock.gif    Blog blog 
= Blog.Find(5);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
using(TransactionScope tran = new TransactionScope())
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
try
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            blog.Delete();
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif            tran.VoteCommit();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
catch
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            tran.VoteRollBack();
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}


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

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

转载于:https://www.cnblogs.com/han-xiao-feng/archive/2006/07/27/461040.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值