Castle ActiveRecord学习实践(5):实现Many–Many关系的映射

摘要:多对多的关系在日常开发中也会经常遇到,在ActiveRecord中我们用HasAndBelongsToMany特性来实现Many-Many的关联,本文将通过一个具体的实例来介绍这一用法。

 

主要内容

1.准备数据库表

2.编写实体类

3.编写测试代码

 

一.准备数据库表

接着在上篇文章中的例子,为了实现多对多的关系,我们引入Community,即每个Blog可以属于多个社区,每个社区也可以有多个Blog

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  Blog_Community (
None.gif
None.gif     blog_Id 
int   NOT   NULL  ,
None.gif
None.gif     community_Id 
int   NOT   NULL  
None.gif
None.gif )
None.gif
None.gif 
None.gif
None.gif 
CREATE   TABLE  Communities (
None.gif
None.gif     community_Id 
int   IDENTITY  ( 1 1 PRIMARY   KEY ,
None.gif
None.gif     community_Name 
varchar  ( 50 ) ,
None.gif
None.gif     community_Intro 
varchar  ( 500
None.gif
None.gif )

 

二.编写实体类代码

为了实现多对多的关系,我们要在BlogCommunity类中分别使用HasAndBelongsToMany特性,不需要编写Blog_Community类。示例代码:

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

None.gif[HasAndBelongsToMany( 
typeof (Community), 
None.gif
None.gif        Table
= " Blog_Community "
None.gif
None.gif        ColumnRef
= "  community_id  "
None.gif
None.gif        ColumnKey
= "  blog_id  "  )]
None.gif
None.gif
public  IList Communitys
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
get dot.gifreturn _community; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
set dot.gif{ _ community = value; }
InBlock.gif
ExpandedBlockEnd.gif}

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

None.gif[HasAndBelongsToMany( 
typeof (Blog), 
None.gif
None.gif        Table
= " Blog_Community "
None.gif
None.gif        ColumnRef
= " blog_id "
None.gif
None.gif        ColumnKey
= " community_id "  )]
None.gif
None.gif
public  IList Blogs
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
get dot.gifreturn _blog; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
set dot.gif{ _ blog = value; }
InBlock.gif
ExpandedBlockEnd.gif}


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

指定一个附加SQLWhere子句

Where="IsPost = 0"

Lazy

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

Lazy=true|false

 

Cascade的类型值有如下几种

类型

说明

None

不进行级联操作

SaveUpdate

进行级联Save/Update操作

Delete

进行级联Delete操作

All

进行级联Save/Update/Delete操作

AllDeleteOrphan

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

 

最后完整的实体类如下:

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 _community;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [PrimaryKey(PrimaryKeyType.Identity, 
"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    [HasAndBelongsToMany(
typeof(Community),
InBlock.gif
InBlock.gif            Table
="Blog_Community",
InBlock.gif
InBlock.gif            ColumnRef
=" community_id ",
InBlock.gif
InBlock.gif            ColumnKey
=" blog_id " )]
InBlock.gif
InBlock.gif    
public IList Communities
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _community; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _community = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.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}

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

None.gif
None.gif[ActiveRecord(
" Communities " )]
None.gif
None.gif
public   class  Community : 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 _intro;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
private IList _blog;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    [PrimaryKey(PrimaryKeyType.Identity, 
"Community_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(
"Community_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(
"Community_Intro")]
InBlock.gif
InBlock.gif    
public String Author
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _intro; }
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _intro = value; }
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
InBlock.gif
InBlock.gif    [HasAndBelongsToMany(
typeof(Blog),
InBlock.gif
InBlock.gif            Table
="Blog_Community",
InBlock.gif
InBlock.gif            ColumnRef
="blog_id",
InBlock.gif
InBlock.gif            ColumnKey
="community_id" )]
InBlock.gif
InBlock.gif    
public IList Blogs
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    
public static void DeleteAll()
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        DeleteAll( 
typeof(Community) );
InBlock.gif
ExpandedSubBlockEnd.gif    }

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

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

InBlock.gif
ExpandedBlockEnd.gif}

 

三.编写测试代码

下面是我写的一些简单的测试代码,有兴趣的可以看一下。

1.级联增加:新增一个Blog,让它同时属于好几个社区

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 
= "Tech Space";
InBlock.gif
InBlock.gif    blog.Author 
= "Terrylee";
InBlock.gif
InBlock.gif    
InBlock.gif
InBlock.gif    
//属于ID为1,2社区
InBlock.gif

InBlock.gif    ArrayList list 
= new ArrayList();
InBlock.gif
InBlock.gif    list.Add(Community.Find(
1));
InBlock.gif
InBlock.gif    list.Add(Community.Find(
2));
InBlock.gif
InBlock.gif    blog.Communities 
= list;
InBlock.gif
InBlock.gif    
InBlock.gif
InBlock.gif    
//保存
InBlock.gif

InBlock.gif    blog.Save();
InBlock.gif
ExpandedBlockEnd.gif}


2.级联更新:对一个已经存在Blog,更改它属于更多的社区

None.gif [Test]
None.gif
None.gif
public   void  TestCascadingUpdate()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
//测试1:查找一个Blog
InBlock.gif

InBlock.gif    Blog blog 
= Blog.Find(10);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    IList clist 
= blog.Communities;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    clist.Add(Community.Find(
4));
InBlock.gif
InBlock.gif    clist.Add(Community.Find(
3));
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    blog.Save();
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
//测试2:查找一个Community
InBlock.gif

InBlock.gif    Community community 
= Community.Find(3);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    IList blist 
= community.Blogs;
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    blist.Add(Blog.Find(
8));
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    community.Save();
InBlock.gif
ExpandedBlockEnd.gif}

 

3.级联删除:删除一个Blog,级联表中对应的记录应该删除,但Community不能删除,因为还有别的Blog和它关联

None.gif [Test]
None.gif
None.gif
public   void  TestCascadingDelete()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
//测试1:删除Blog
InBlock.gif

InBlock.gif    Blog blog 
= Blog.Find(10);
InBlock.gif
InBlock.gif    
InBlock.gif
InBlock.gif    
using(TransactionScope btran = 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            btran.VoteCommit();
InBlock.gif
ExpandedSubBlockEnd.gif        }

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

InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
//测试2:删除Community
InBlock.gif

InBlock.gif    Community community 
= Community.Find(3);
InBlock.gif
InBlock.gif 
InBlock.gif
InBlock.gif    
using(TransactionScope ctran = 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            community.Delete();
InBlock.gif
InBlock.gif            ctran.VoteCommit();
InBlock.gif
ExpandedSubBlockEnd.gif        }

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

InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

 

好了,关于Many-Many关联映射就写这么多了,内容比较简单。下篇文章我会介绍在ActiveRecord中实现延迟加载和使用Where子句。

 

参考资料

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值