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.gif
{
InBlock.gif
InBlock.gif    
//
InBlock.gif

ExpandedBlockEnd.gif}

User类添加特性,其实就是告诉 ActiveRecordUser类所对应的数据库中的数据表名为 Users
None.gif [ActiveRecord( " Users " )]
None.gif
public   class  User : ActiveRecordBase
ExpandedBlockStart.gif
{
InBlock.gif    
//
ExpandedBlockEnd.gif
}

下面我们的工作就是为实体类添加属性
None.gif [ActiveRecord( " Users " )]
None.gif
public   class  User : ActiveRecordBase
ExpandedBlockStart.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.gif    
{
ExpandedSubBlockStart.gif        
get return _id; }
ExpandedSubBlockStart.gif        
set { _id = value; }
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    [Property(
"LogonName")]
InBlock.gif    
public string Name
ExpandedSubBlockStart.gif    
{
ExpandedSubBlockStart.gif        
get return _name; }
ExpandedSubBlockStart.gif        
set { _name = value; }
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    [Property(
"Password")]
InBlock.gif    
public string Password
ExpandedSubBlockStart.gif    
{
ExpandedSubBlockStart.gif        
get return _password; }
ExpandedSubBlockStart.gif        
set { _password = value; }
ExpandedSubBlockEnd.gif    }

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

InBlock.gif    
InBlock.gif    [Property(
"LastLogon")]
InBlock.gif    
public DateTime LastLogon
ExpandedSubBlockStart.gif    
{
ExpandedSubBlockStart.gif        
get return _lastLogon; }
ExpandedSubBlockStart.gif        
set {_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.gif
{
InBlock.gif    
//……
InBlock.gif

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

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

InBlock.gif
InBlock.gif    
public static User Find(int id)
ExpandedSubBlockStart.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.gif
{
ExpandedSubBlockStart.gif    
/// <summary>
InBlock.gif    
/// User 的摘要说明。
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    [ActiveRecord("Users")]
InBlock.gif    
public class User : ActiveRecordBase
ExpandedSubBlockStart.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.gif        
{
ExpandedSubBlockStart.gif            
get return _id; }
ExpandedSubBlockStart.gif            
set { _id = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif        
InBlock.gif        [Property(
"LogonName")]
InBlock.gif        
public string Name
ExpandedSubBlockStart.gif        
{
ExpandedSubBlockStart.gif            
get return _name; }
ExpandedSubBlockStart.gif            
set { _name = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif        
InBlock.gif        [Property(
"Password")]
InBlock.gif        
public string Password
ExpandedSubBlockStart.gif        
{
ExpandedSubBlockStart.gif            
get return _password; }
ExpandedSubBlockStart.gif            
set { _password = value; }
ExpandedSubBlockEnd.gif        }

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

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

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

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

InBlock.gif
InBlock.gif        
public static User Find(int id)
ExpandedSubBlockStart.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.gif
{
InBlock.gif    User user 
= new User();
InBlock.gif
InBlock.gif    user.Name 
= "Terrylee";
InBlock.gif    user.Password 
= "aaa";
InBlock.gif    user.Address 
= "[email]lhj_cauc@163.com[/email]";
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.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.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.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 
= "[email]chwkai@163.com[/email]";
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.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.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.gif
{
InBlock.gif    
using Castle.ActiveRecord;
InBlock.gif    
InBlock.gif    
InBlock.gif    [ActiveRecord(
"Users")]
InBlock.gif    
public class User : ActiveRecordBase
ExpandedSubBlockStart.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.gif        
{
InBlock.gif            
get
ExpandedSubBlockStart.gif            
{
InBlock.gif                
return this._logonID;
ExpandedSubBlockEnd.gif            }

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

ExpandedSubBlockEnd.gif        }

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

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

ExpandedSubBlockEnd.gif        }

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

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

ExpandedSubBlockEnd.gif        }

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

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

ExpandedSubBlockEnd.gif        }

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

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

ExpandedSubBlockEnd.gif        }

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

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

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

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













本文转自lihuijun51CTO博客,原文链接: http://blog.51cto.com/terrylee/67655 ,如需转载请自行联系原作者


相关文章
|
关系型数据库 Java 测试技术
|
Oracle 关系型数据库 MySQL
|
应用服务中间件 数据库
|
Java uml Android开发