Castle ActiveRecord 泛型应用

本文介绍如何在CastleActiveRecord中使用泛型进行强类型操作,通过实例展示了Blog与Post的一对多关系,并详细解析了EntitySet和EntityRef的用法。

    Castle ActiveRecord在.Net2.0下支持泛型,这极大的方便了我们创建强类型集合以及对对象的强类型操作.本文引用了Castle站点上泛型的例子来详细介绍如何应用泛型. 另外你需要在这里找到NHibernate.Generics 来支持AR对泛型的扩展.这个例子描述了最简单的Blog与Post一对多的关系,为了让示例更清晰,做了少许修改. 

    NHibernate.Generics 中包含了若干供我们引用的泛型集合EntitySet,EntityList,EntityDictionary等,以及与这些集合相匹配的EntityRef.

ContractedBlock.gif ExpandedBlockStart.gif DB结构
CREATE TABLE [dbo].[Blogs] (
    
[blog_id] [int] IDENTITY (11NOT NULL ,
    
[blog_name] [varchar] (50NULL ,    
ON [PRIMARY]

CREATE TABLE [dbo].[Posts] (
    
[post_id] [int] IDENTITY (11NOT NULL ,
    
[post_title] [varchar] (50NULL ,
    
[post_contents] [text] NULL ,    
    
[post_blogid] [int] NULL ,    
ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

ContractedBlock.gif ExpandedBlockStart.gif Bolg Class
None.gif[ActiveRecord]
None.gif
public class Blog : ActiveRecordBase
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    EntitySet
<Post> _posts;
InBlock.gif    
int _id;
InBlock.gif    
string _name;
InBlock.gif
InBlock.gif    
private Blog()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        _posts 
= new EntitySet<Post>(
ExpandedSubBlockStart.gifContractedSubBlock.gif                
delegate(Post p) dot.gif{ p.Blog = this; },
ExpandedSubBlockStart.gifContractedSubBlock.gif                
delegate(Post p) dot.gif{ p.Blog = null; }
InBlock.gif            );
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    [PrimaryKey(PrimaryKeyType.Identity, 
"blog_id", Access = PropertyAccess.NoSetterCamelCaseUnderscore)]
InBlock.gif    
public int Id
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _id; }
ExpandedSubBlockEnd.gif    }

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

InBlock.gif
InBlock.gif    [HasMany(
typeof(Post), "post_blogId""Posts", Inverse = true
InBlock.gif        CustomAccess 
= Generics.Access, RelationType = RelationType.Set)]
InBlock.gif    
public ICollection<Post> Posts
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _posts; }
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public static Blog FindByName(string value)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return ActiveRecordBase<Blog>.FindOne(new EqExpression("Name", value));
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

    在BlogClass中看到了这样的定义EntitySet<Post> _posts.

    首先看看构造函数中对它的初始化2个匿名delegate的作用是当向Bolg.Posts集合中添加或移除一个Post时,自动添加或移除Post.Bolg属性设置.省却了每次都需要做双向设置.

    再来看一下Bolg.Posts的公开属性返回一个ICollection的接口是很重要的而不是具体类型,这样屏蔽了直接使用NHibernate.Generics中的集合所带来的依赖.

    最后看看顶上的attribute,对应关系不多讲,CustomAccess = Generics.Access是一定要标明的描述了泛型访问方式.RelationType = RelationType.Set同样要标识明确RelationType.Set对应EntitySet, RelationType.Bag则对应EntityList.Inverse属性有可无了,它指明了即使Bolg.Posts中的Post没有被存入数据库Bolg一样可以被先保存,通常我认为使用Cascade = ManyRelationCascadeEnum.All会更好.

    还有一点需要注意的是应用了泛型的私有变量命名如 _posts,按照AR目前最新的DailyBulid你必须按照下划线这样的格式命名,Access属性的设置似乎是无效的.如果使用其他方式会出错.

    泛型集合之后来关注下其他问题.

    你看到了Id的attribute,由于id是自动生成的所以无需设置set访问器,Access = PropertyAccess.NoSetterCamelCaseUnderscore会帮你赋值NoSetterCamelCaseUnderscore指出Id属性的私有变量命名方式是无set访问器的以下划线开头的Camel命名方式.

    对对象的数据库操作同样可以使用泛型,可以看到FindByName中省去了麻烦的转型.

ContractedBlock.gif ExpandedBlockStart.gif Post Class
None.gif[ActiveRecord]
None.gif
public class Post : ActiveRecordBase
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
int _id;
InBlock.gif    
string _title;
InBlock.gif    
string _content;
InBlock.gif
InBlock.gif    EntityRef
<Blog> _blog;
InBlock.gif
InBlock.gif    [PrimaryKey(PrimaryKeyType.Identity, 
"post_id",
InBlock.gif        Access 
= PropertyAccess.NoSetterCamelCaseUnderscore)]
InBlock.gif    
public int Id
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _id; }
ExpandedSubBlockEnd.gif    }

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

InBlock.gif
InBlock.gif    [Property(
"post_content")]
InBlock.gif    
public string Content
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _content; }
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _content = value; }
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    [BelongsTo(
"post_blog_id",
InBlock.gif        CustomAccess 
= Generics.Access)]
InBlock.gif    
public Blog Blog
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _blog.Value; }
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _blog.Value = value; }
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public Post()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        _blog 
= new EntityRef<Blog>(
ExpandedSubBlockStart.gifContractedSubBlock.gif                
delegate(Tests.Blog b) dot.gif{ b.Posts.Add(this); },
ExpandedSubBlockStart.gifContractedSubBlock.gif                
delegate(Tests.Blog b) dot.gif{ b.Posts.Remove(this); }
InBlock.gif            );
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

    在PostClass中EntityRef是一个对对象的包装,使得它能够添加delegate与Entityxx集合对应来处理添加或移除的同步操作.在Post.Blog属性中可以通过_blog.Value来访问与设置EntityRef包装的值.attribute并没有特别支处,只是CustomAccess = Generics.Access也是不可缺少的属性.

    现在你可以使用ActiveRecord轻松编程了.

转载于:https://www.cnblogs.com/simonw/archive/2006/08/11/474044.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值