摘要:多对多的关系在日常开发中也会经常遇到,在ActiveRecord中我们用HasAndBelongsToMany特性来实现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子句。
参考资料
Castle
的官方网站http://www.castleproject.org
作者:
TerryLee
出处:
http://terrylee.cnblogs.com