Castle ActiveRecord学习实践(1):快速入门指南

摘要:最近几天有时间看了一下Castle,原来它的功能是如此的强大,从数据访问框架到IOC容器,再到WEB框架,基本包括了整个开发过程中的所有东西,看来得好好学习研究一下了,并且打算把自己学习过程的一些东西记录下来。先从ActiveRecord开始吧,ActiveRecord提供的简洁的O/R映射给我留下了很深的印象,本文将通过一个简单对象的CRUD操作来带你快速走进Castle ActiveRecord

主要内容

1.概述

2.准备相关的数据表

3.编写User实体类

4.构建配置信息

5.开始CRUD操作

6.使用ActiveRecord Generator生成实体类代码

 

一.概述

如果你用过NHibernate,一定会对在NHibernate中编写.hbm.xml文件印象深刻,我也是。而在Castle ActiveRecord中,我们不用再为编写繁冗复杂的映射文件而头疼,ActiveRecordCastle中提供的一个数据访问框架,它在底层封装了NHibernate的操作,使用特性来代替映射文件,它提供的简洁的O/R映射会让你惊叹原来实现持久化数据层是那么简单。下面我们通过一个简单对象的CRUD操作来快速进入Castle ActiveRecord

 

二.准备相关的数据表

假定数据库中有这样一张用户表,用来保存用户的信息,如下

None.gif CREATE   TABLE   [ dbo ] . [ Users ]  (
None.gif    
[ LogonID ]   [ int ]   IDENTITY  ( 1 1 NOT   NULL  ,
None.gif    
[ LogonName ]   [ varchar ]  ( 40 ) COLLATE Chinese_PRC_CI_AS  NULL  ,
None.gif    
[ Password ]   [ varchar ]  ( 20 ) COLLATE Chinese_PRC_CI_AS  NULL  ,
None.gif    
[ EmailAddress ]   [ varchar ]  ( 40 ) COLLATE Chinese_PRC_CI_AS  NULL  ,
None.gif    
[ LastLogon ]   [ datetime ]   NULL  
None.gif
ON   [ PRIMARY ]
None.gif
GO


三.编写User实体类

首先我们新建一个User类并让它继承于ActiveRecordBase

None.gif public   class  User : ActiveRecordBase
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
//
InBlock.gif

ExpandedBlockEnd.gif}


User类添加特性,其实就是告诉ActiveRecordUser类所对应的数据库中的数据表名为Users

None.gif [ActiveRecord( " Users " )]
None.gif
public   class  User : ActiveRecordBase
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
//
ExpandedBlockEnd.gif
}


下面我们的工作就是为实体类添加属性

None.gif [ActiveRecord( " Users " )]
None.gif
public   class  User : ActiveRecordBase
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
private int _id;
InBlock.gif
InBlock.gif    
private string _name;
InBlock.gif
InBlock.gif    
private string _password;
InBlock.gif
InBlock.gif    
private string _emailAddress;
InBlock.gif
InBlock.gif    
private DateTime _lastLogon;
InBlock.gif
InBlock.gif    [PrimaryKey(PrimaryKeyType.Identity, 
"LogonID")]
InBlock.gif    
public int Id
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _id; }
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _id = value; }
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    [Property(
"LogonName")]
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    [Property(
"Password")]
InBlock.gif    
public string Password
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _password; }
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _password = value; }
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    [Property(
"EmailAddress")]
InBlock.gif    
public string Address
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gifreturn _emailAddress; }
ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{ _emailAddress = value; }
ExpandedSubBlockEnd.gif    }

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

ExpandedBlockEnd.gif}


大家可能注意到了,每一个属性上面都加上了特性[Property()]。简单的说明一下,这里用[PrimaryKey]特性指定Id作为主键,并且说明了主键的类型为自增型的,用PrimaryKeyType.Identity来说明,在后续文章中我会详细说明的。如果属性名和字段名一致,[Property()]中可以为空,也可以写上字段的名字。

下一步我们为实体类根据需要加上静态的操作方法,至于Create()Update()Delete()Save()等方法则会直接从ActiveRecordBase基类中继承

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

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

InBlock.gif
InBlock.gif    
public static IList FindAll()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return (IList) FindAll( typeof(User) );
ExpandedSubBlockEnd.gif    }

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

ExpandedBlockEnd.gif}

 

整个完成后的实体类代码

None.gif using  System;
None.gif
using  System.Collections;
None.gif
using  Castle.ActiveRecord;
None.gif
None.gif
namespace  ARDemo
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// User 的摘要说明。
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    [ActiveRecord("Users")]
InBlock.gif    
public class User : ActiveRecordBase
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private int _id;
InBlock.gif
InBlock.gif        
private string _name;
InBlock.gif
InBlock.gif        
private string _password;
InBlock.gif
InBlock.gif        
private string _emailAddress;
InBlock.gif
InBlock.gif        
private DateTime _lastLogon;
InBlock.gif
InBlock.gif        [PrimaryKey(PrimaryKeyType.Identity, 
"LogonID")]
InBlock.gif        
public int Id
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _id; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{ _id = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif        
InBlock.gif        [Property(
"LogonName")]
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        [Property(
"Password")]
InBlock.gif        
public string Password
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _password; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{ _password = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif        
InBlock.gif        [Property(
"EmailAddress")]
InBlock.gif        
public string Address
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _emailAddress; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{ _emailAddress = value; }
ExpandedSubBlockEnd.gif        }

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

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

InBlock.gif
InBlock.gif        
public static IList FindAll()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return (IList) FindAll( typeof(User) );
ExpandedSubBlockEnd.gif        }

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

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

 

四.构建配置信息

现在我们要告诉ActiveRecord相关的数据库、数据驱动等信息,最简单的就是使用配置文件

None.gif <? xml version="1.0" encoding="utf-8"  ?>
None.gif
< configuration >
None.gif    
< configSections >
None.gif        
< section  name ="activerecord"  type ="Castle.ActiveRecord.Framework.Config.ActiveRecordSectionHandler, Castle.ActiveRecord"   />
None.gif    
</ configSections >
None.gif    
< activerecord >
None.gif        
< config >
None.gif            
< add  key ="hibernate.connection.driver_class"  value ="NHibernate.Driver.SqlClientDriver"   />
None.gif            
< add  key ="hibernate.dialect"  value ="NHibernate.Dialect.MsSql2000Dialect"   />
None.gif            
< add  key ="hibernate.connection.provider"  value ="NHibernate.Connection.DriverConnectionProvider"   />
None.gif            
< add  key ="hibernate.connection.connection_string"  value ="UID=sa;Password=sa;Initial Catalog=ARDemo;Data Source=."   />
None.gif        
</ config >
None.gif    
</ activerecord >
None.gif
</ configuration >


用过NHibernate的朋友一定会对这段配置代码很熟悉,没错,因为ActiveRecord在底层封装了NHibernate,所以这里的配置跟使用NHibernate时的配置一样,同样是指定了数据源驱动,连接字符串等信息。如果使用了配置文件在代码中只要这样去初始化就可以了

None.gif IConfigurationSource source  =  System.Configuration.ConfigurationSettings.GetConfig( " activerecord " as  IConfigurationSource;
None.gifActiveRecordStarter.Initialize( source, 
typeof (User) );


我们也可以不使用配置文件,而使用代码指定的方式,但是由于这种方式相当于硬编码了,不大推荐大家使用这种方式:

None.gif InPlaceConfigurationSource source  =   new  InPlaceConfigurationSource();
None.gif
None.gifHashtable properties 
=   new  Hashtable();
None.gif
None.gifproperties.Add(
" hibernate.connection.driver_class " " NHibernate.Driver.SqlClientDriver " );
None.gifproperties.Add(
" hibernate.dialect " " NHibernate.Dialect.MsSql2000Dialect " );
None.gifproperties.Add(
" hibernate.connection.provider " " NHibernate.Connection.DriverConnectionProvider " );
None.gifproperties.Add(
" hibernate.connection.connection_string " " UID=sa;Password=19811218;Initial Catalog=ARDemo;Data Source=. " );
None.gif
None.gifsource.Add( 
typeof (ActiveRecordBase), properties );
None.gif
None.gifActiveRecordStarter.Initialize( source, 
typeof (User) );

 

五.开始CRUD操作

好了,经过了前面的步骤之后,就可以正式开始我们的对象CRUD操作了。

1.增加User对象

None.gif [Test]
None.gif
public   void  AddUser()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    User user 
= new User();
InBlock.gif
InBlock.gif    user.Name 
= "Terrylee";
InBlock.gif    user.Password 
= "aaa";
InBlock.gif    user.Address 
= "lhj_cauc@163.com";
InBlock.gif    user.LastLogon 
= DateTime.Now;
InBlock.gif    
InBlock.gif    user.Create();
ExpandedBlockEnd.gif}


是不是非常简单?我们甚至都没有写过Create()方法,它直接从ActiveRecordBase类继承。我们所做的只是创建这样一个User对象,然后调用它的方法就可以了。

2.查询所有的User对象

None.gif [Test]
None.gif
public   void  FildAll()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    IList list 
= User.FindAll();
InBlock.gif
InBlock.gif    Assert.IsNotNull(list);
InBlock.gif
InBlock.gif    
int actual = list.Count;
InBlock.gif    
int expected = 2;
InBlock.gif
InBlock.gif    Assert.AreEqual(expected,actual);
ExpandedBlockEnd.gif}


3.查询某一个指定IdUser对象

None.gif [Test]
None.gif
public   void  Fild()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int id = 5;
InBlock.gif    User actual 
= User.Find(id);
InBlock.gif
InBlock.gif    Assert.IsNotNull(actual);
InBlock.gif    Assert.AreEqual(
"Terrylee",actual.Name);
InBlock.gif    Assert.AreEqual(
"aaa",actual.Password);
ExpandedBlockEnd.gif}


4.修改User对象

None.gif [Test]
None.gif
public   void  UpdateUser()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    User user 
= new User();
InBlock.gif
InBlock.gif    user.Id 
= 5;
InBlock.gif    user.Name 
= "Aero";
InBlock.gif    user.Password 
= "aaa";
InBlock.gif    user.Address 
= "chwkai@163.com";
InBlock.gif    user.LastLogon 
= DateTime.Now;
InBlock.gif
InBlock.gif    user.Update();
ExpandedBlockEnd.gif}


5.删除User对象

None.gif [Test]
None.gif
public   void  DeleteUser()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    User user 
= new User();
InBlock.gif
InBlock.gif    user.Id 
= 7;
InBlock.gif    user.Delete();
ExpandedBlockEnd.gif}


6.删除所有的User对象

None.gif [Test]
None.gif
public   void  DeleteAll()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    User.DeleteAll();
ExpandedBlockEnd.gif}


可以看到,整个过程非常的简洁简单,没有一点多余复杂的代码,相信你已经开始体会到了ActiveRecord的魅力了。唯一有一点你会感到不舒服的是已经有了数据库表还需要手工编写实体类代码,这个不用担心,ActiveRecord已经为我们提供了代码生成工具ActiveRecord Generator

六.使用ActiveRecord Generator生成实体类代码

1.执行Castle.ActiveRecord.Generator.exe,位于目录C:\Program Files\Castle\Bin\net-1.1\下面,可以看到如下界面,选择Project Explorer面板

 

2.点击“Add DataBase Connection”图标,如下图中红色方框所示,弹出设置连接字符串对话框,我们首先要为数据库起一个别名,这个名字可以跟数据库名不一样,在后面我们会用到

 

注意:如果连接数据库为SQL Server2000数据库,必须在弹出的对话框中选中允许保存密码选项,否则点击OK按钮时会报登录失败的错误!这点不知道是不是我机器的设置问题,如果有朋友遇到这样的错误,不妨一试。

 

3.点击OK后,选择ActiveRecord Components面板

 

 

 

4.拖动ActiveRecord到左边的空白区域,会出现如下界面,选择我们刚才设置的数据库别名

 

5.此后操作有选择子段,设置类名等,全部完成后界面如下:

 

6.选择Project菜单下的Generate Code,输入命名空间,文件设置路径,并选择所要生成代码语言

注意:有一个选项是否覆盖已经存在的文件,可以根据自己的实际情况选择

7.最后生成的完整实体类代码如下

None.gif //  
None.gif
//  Generated by ActiveRecord Generator
None.gif
//  
None.gif
//
None.gif
namespace  ARDemo
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
using Castle.ActiveRecord;
InBlock.gif    
InBlock.gif    
InBlock.gif    [ActiveRecord(
"Users")]
InBlock.gif    
public class User : ActiveRecordBase
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
InBlock.gif        
private int _logonID;
InBlock.gif        
InBlock.gif        
private string _logonName;
InBlock.gif        
InBlock.gif        
private string _password;
InBlock.gif        
InBlock.gif        
private string _emailAddress;
InBlock.gif        
InBlock.gif        
private System.DateTime _lastLogon;
InBlock.gif        
InBlock.gif        [PrimaryKey(PrimaryKeyType.Native)]
InBlock.gif        
public int LogonID
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return this._logonID;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this._logonID = value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
InBlock.gif        [Property()]
InBlock.gif        
public string LogonName
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return this._logonName;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this._logonName = value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
InBlock.gif        [Property()]
InBlock.gif        
public string Password
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return this._password;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this._password = value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
InBlock.gif        [Property()]
InBlock.gif        
public string EmailAddress
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return this._emailAddress;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this._emailAddress = value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
InBlock.gif        [Property()]
InBlock.gif        
public System.DateTime LastLogon
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return this._lastLogon;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this._lastLogon = value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

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

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

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}


大家还应该注意的一点是生成One-Many/Many-One等关系的实体类文件时可能会出现一些问题,需要对生成的代码手工改动。最后希望和研究Castle的朋友能够多多交流!

 

参考资料

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值