数据库结构设计
本例中,两个对象通过一个关联表实现多对多关系,因此实际上有三个数据表。SQL Server 2000 生成的 SQL 建表脚本如下:
CREATE
TABLE
[
WebFolder_Resource
]
(
[ ResourceID ] [ int ] IDENTITY ( 1 , 1 ) NOT NULL ,
[ ResourceName ] [ varchar ] ( 50 ) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[ RequestName ] [ varchar ] ( 50 ) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[ ShowOrder ] [ varchar ] ( 10 ) COLLATE Chinese_PRC_CI_AS NOT NULL
) ON [ PRIMARY ]
GO
CREATE TABLE [ WebFolder_Role ] (
[ RoleID ] [ int ] IDENTITY ( 1 , 1 ) NOT NULL ,
[ RoleName ] [ varchar ] ( 50 ) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[ RoleDescription ] [ varchar ] ( 50 ) COLLATE Chinese_PRC_CI_AS NOT NULL
) ON [ PRIMARY ]
GO
CREATE TABLE [ WebFolder_RoleResource ] (
[ RoleID ] [ int ] NOT NULL ,
[ ResourceID ] [ int ] NOT NULL
) ON [ PRIMARY ]
GO
ALTER TABLE [ WebFolder_Resource ] ADD
CONSTRAINT [ PK_WebFolder_Resource ] PRIMARY KEY CLUSTERED
(
[ ResourceID ]
) ON [ PRIMARY ]
GO
ALTER TABLE [ WebFolder_Role ] ADD
CONSTRAINT [ PK_WebFolder_Role ] PRIMARY KEY CLUSTERED
(
[ RoleID ]
) ON [ PRIMARY ]
GO
[ ResourceID ] [ int ] IDENTITY ( 1 , 1 ) NOT NULL ,
[ ResourceName ] [ varchar ] ( 50 ) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[ RequestName ] [ varchar ] ( 50 ) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[ ShowOrder ] [ varchar ] ( 10 ) COLLATE Chinese_PRC_CI_AS NOT NULL
) ON [ PRIMARY ]
GO
CREATE TABLE [ WebFolder_Role ] (
[ RoleID ] [ int ] IDENTITY ( 1 , 1 ) NOT NULL ,
[ RoleName ] [ varchar ] ( 50 ) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[ RoleDescription ] [ varchar ] ( 50 ) COLLATE Chinese_PRC_CI_AS NOT NULL
) ON [ PRIMARY ]
GO
CREATE TABLE [ WebFolder_RoleResource ] (
[ RoleID ] [ int ] NOT NULL ,
[ ResourceID ] [ int ] NOT NULL
) ON [ PRIMARY ]
GO
ALTER TABLE [ WebFolder_Resource ] ADD
CONSTRAINT [ PK_WebFolder_Resource ] PRIMARY KEY CLUSTERED
(
[ ResourceID ]
) ON [ PRIMARY ]
GO
ALTER TABLE [ WebFolder_Role ] ADD
CONSTRAINT [ PK_WebFolder_Role ] PRIMARY KEY CLUSTERED
(
[ RoleID ]
) ON [ PRIMARY ]
GO
依赖的类库
You must reference the following set of assemblies to use ActiveRecord:
- Castle.ActiveRecord.dll
- Castle.Model.dll
- Nullables.dll
But ActiveRecord also depends on NHibernate, so you must reference the following as well:
- NHibernate.dll
- Castle.DynamicProxy.dll (Curious? Check DynamicProxy)
- Nullables.NHibernate.dll
- log4net.dll
- Iesi.Collections.dll
领域对象
Role.cs (StephenCat.WebFolder.Domain.Role)
using
System;
using System.Collections;
using Castle.ActiveRecord;
namespace StephenCat.WebFolder.Domain
{
/// <summary>
/// Role 的摘要说明。
/// </summary>
[ActiveRecord( " WebFolder_Role " )]
public class Role : ActiveRecordBase
{
/// <summary>
/// 创建一个角色
/// </summary>
public Role()
{
}
private int _id;
private String _name;
private String _description;
private IList _accounts;
private IList _resources;
/// <summary>
/// 角色编号
/// </summary>
[PrimaryKey(PrimaryKeyType.Native, " RoleID " )]
public int Id
{
get { return _id; }
set { _id = value; }
}
/// <summary>
/// 角色名称
/// </summary>
[Property( " RoleName " )]
public String Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
/// 角色说明
/// </summary>
[Property( " RoleDescription " )]
public String Description
{
get { return _description; }
set { _description = value; }
}
/// <summary>
/// 角色所拥有的帐号集合
/// </summary>
[HasMany( typeof (Resource), Table = " Account " , ColumnKey = " RoleID " , Lazy = true )]
public IList Accounts
{
get { return _accounts; }
set { _accounts = value; }
}
/// <summary>
/// 角色所拥有的资源集合
/// </summary>
[HasAndBelongsToMany( typeof (Resource),
Table = " WebFolder_RoleResource " ,
ColumnRef = " ResourceID " , ColumnKey = " RoleID " )]
public IList Resources
{
get { return _resources; }
set { _resources = value; }
}
/// <summary>
/// 删除所有角色
/// </summary>
public static void DeleteAll()
{
DeleteAll( typeof (Role) );
}
/// <summary>
/// 获取所有角色
/// </summary>
/// <returns> 角色集合 </returns>
public static Role[] FindAll()
{
return (Role[]) FindAll( typeof (Role) );
}
/// <summary>
/// 获取一个角色
/// </summary>
/// <param name="id"> 角色编号 </param>
/// <returns> 角色实体 </returns>
public static Role Find( int id)
{
return (Role) FindByPrimaryKey( typeof (Role), id );
}
}
}
using System.Collections;
using Castle.ActiveRecord;
namespace StephenCat.WebFolder.Domain
{
/// <summary>
/// Role 的摘要说明。
/// </summary>
[ActiveRecord( " WebFolder_Role " )]
public class Role : ActiveRecordBase
{
/// <summary>
/// 创建一个角色
/// </summary>
public Role()
{
}
private int _id;
private String _name;
private String _description;
private IList _accounts;
private IList _resources;
/// <summary>
/// 角色编号
/// </summary>
[PrimaryKey(PrimaryKeyType.Native, " RoleID " )]
public int Id
{
get { return _id; }
set { _id = value; }
}
/// <summary>
/// 角色名称
/// </summary>
[Property( " RoleName " )]
public String Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
/// 角色说明
/// </summary>
[Property( " RoleDescription " )]
public String Description
{
get { return _description; }
set { _description = value; }
}
/// <summary>
/// 角色所拥有的帐号集合
/// </summary>
[HasMany( typeof (Resource), Table = " Account " , ColumnKey = " RoleID " , Lazy = true )]
public IList Accounts
{
get { return _accounts; }
set { _accounts = value; }
}
/// <summary>
/// 角色所拥有的资源集合
/// </summary>
[HasAndBelongsToMany( typeof (Resource),
Table = " WebFolder_RoleResource " ,
ColumnRef = " ResourceID " , ColumnKey = " RoleID " )]
public IList Resources
{
get { return _resources; }
set { _resources = value; }
}
/// <summary>
/// 删除所有角色
/// </summary>
public static void DeleteAll()
{
DeleteAll( typeof (Role) );
}
/// <summary>
/// 获取所有角色
/// </summary>
/// <returns> 角色集合 </returns>
public static Role[] FindAll()
{
return (Role[]) FindAll( typeof (Role) );
}
/// <summary>
/// 获取一个角色
/// </summary>
/// <param name="id"> 角色编号 </param>
/// <returns> 角色实体 </returns>
public static Role Find( int id)
{
return (Role) FindByPrimaryKey( typeof (Role), id );
}
}
}
Resource.cs (StephenCat.WebFolder.Domain.Resource)
using
System;
using System.Collections;
using Castle.ActiveRecord;
namespace StephenCat.WebFolder.Domain
{
/// <summary>
/// Resource 的摘要说明。
/// </summary>
[ActiveRecord( " WebFolder_Resource " )]
public class Resource : ActiveRecordBase
{
/// <summary>
/// 创建一个资源
/// </summary>
public Resource()
{
}
private int _id;
private String _name;
private String _requestname;
private String _showorder;
private IList _roles;
/// <summary>
/// 资源编号
/// </summary>
[PrimaryKey(PrimaryKeyType.Native, " ResourceID " )]
public int Id
{
get { return _id; }
set { _id = value; }
}
/// <summary>
/// 资源名称
/// </summary>
[Property( " ResourceName " )]
public String Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
/// 请求名称
/// </summary>
[Property( " RequestName " )]
public String RequestName
{
get { return _requestname; }
set { _requestname = value; }
}
/// <summary>
/// 序号
/// </summary>
[Property( " ShowOrder " )]
public String ShowOrder
{
get { return _showorder; }
set { _showorder = value; }
}
/// <summary>
/// 资源所拥有的角色集合
/// </summary>
[HasAndBelongsToMany( typeof (Role),
Table = " WebFolder_RoleResource " ,
ColumnRef = " RoleID " , ColumnKey = " ResourceID " )]
public IList Roles
{
get { return _roles; }
set { _roles = value; }
}
/// <summary>
/// 删除所有资源
/// </summary>
public static void DeleteAll()
{
DeleteAll( typeof (Resource) );
}
/// <summary>
/// 获取所有资源
/// </summary>
/// <returns> 资源集合 </returns>
public static Resource[] FindAll()
{
return (Resource[]) FindAll( typeof (Resource) );
}
/// <summary>
/// 获取一个资源
/// </summary>
/// <param name="id"> 资源编号 </param>
/// <returns> 资源集合 </returns>
public static Resource Find( int id)
{
return (Resource) FindByPrimaryKey( typeof (Resource), id );
}
}
}
using System.Collections;
using Castle.ActiveRecord;
namespace StephenCat.WebFolder.Domain
{
/// <summary>
/// Resource 的摘要说明。
/// </summary>
[ActiveRecord( " WebFolder_Resource " )]
public class Resource : ActiveRecordBase
{
/// <summary>
/// 创建一个资源
/// </summary>
public Resource()
{
}
private int _id;
private String _name;
private String _requestname;
private String _showorder;
private IList _roles;
/// <summary>
/// 资源编号
/// </summary>
[PrimaryKey(PrimaryKeyType.Native, " ResourceID " )]
public int Id
{
get { return _id; }
set { _id = value; }
}
/// <summary>
/// 资源名称
/// </summary>
[Property( " ResourceName " )]
public String Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
/// 请求名称
/// </summary>
[Property( " RequestName " )]
public String RequestName
{
get { return _requestname; }
set { _requestname = value; }
}
/// <summary>
/// 序号
/// </summary>
[Property( " ShowOrder " )]
public String ShowOrder
{
get { return _showorder; }
set { _showorder = value; }
}
/// <summary>
/// 资源所拥有的角色集合
/// </summary>
[HasAndBelongsToMany( typeof (Role),
Table = " WebFolder_RoleResource " ,
ColumnRef = " RoleID " , ColumnKey = " ResourceID " )]
public IList Roles
{
get { return _roles; }
set { _roles = value; }
}
/// <summary>
/// 删除所有资源
/// </summary>
public static void DeleteAll()
{
DeleteAll( typeof (Resource) );
}
/// <summary>
/// 获取所有资源
/// </summary>
/// <returns> 资源集合 </returns>
public static Resource[] FindAll()
{
return (Resource[]) FindAll( typeof (Resource) );
}
/// <summary>
/// 获取一个资源
/// </summary>
/// <param name="id"> 资源编号 </param>
/// <returns> 资源集合 </returns>
public static Resource Find( int id)
{
return (Resource) FindByPrimaryKey( typeof (Resource), id );
}
}
}
单元测试
测试工具
TestDriven.NET 2.0硬件环境
CPU: Intel Pentium IV 2.6c (support hyper-threading)MB: Asus P4P800
RAM: 512 mb DDR
HD: Seagate ATA 120G x 2 (no RAID)
软件环境
OS: Microsoft Windows Server 2003 Enterprise Edition with Service Pack 1IDE: Microsoft Visual Studio.NET 2003 Enterprise Architecture Edition
DB: Microsoft SQL Server 2000 with Service Pack 4
Virtual Memory: 2048 ~ 3096 MB on Drive C and 2048 ~ 3096 MB on Drive D
测试用例及结果
using
System;
//
用于控制台输出
using System.Collections; // 用于 IList 操作
using NUnit.Framework; // 用于单元测试
using System.Reflection;
using Castle.ActiveRecord.Framework.Config; // 用于读取内嵌的 Castle AR 配置
using Castle.ActiveRecord; // 用于启动 AR 特性
using StephenCat.WebFolder.Domain; // 领域对象
namespace StephenCat.WebFolder._TestUnitCase
{
/// <summary>
/// RoleTest 的摘要说明。
/// </summary>
[TestFixture]
public class RoleTest
{
public RoleTest()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
/// <summary>
/// 测试创建一个角色
/// </summary>
[Test]
public void RoleCreateTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
// using(new SessionScope())
// {
Role role = new Role();
role.Name = " sysadmin " ;
role.Description = " administrator1234 " ;
role.Save();
// }
}
/// <summary>
/// 测试不清除原来记录的情况下向角色添加三个资源(循环 n 次测试)。
/// </summary>
[Test]
public void RoleAddAgainResourceTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
Role role = Role.Find( 3 );
role.Resources.Add(Resource.Find( 2 ));
role.Resources.Add(Resource.Find( 3 ));
role.Resources.Add(Resource.Find( 5 ));
role.Update(); // 循环三次会出现九条记录。AR 不会考虑仅仅保留唯一记录。
/*
* 控制台输出:
------ Test started: Assembly: StephenCat.WebFolder.dll ------
1 passed, 0 failed, 0 skipped, took 2.27 seconds.
*/
}
/// <summary>
/// 测试删除所有角色所拥有的资源
/// </summary>
[Test]
public void RoleRemoveAllResourceTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
Role role = Role.Find( 3 );
role.Resources.Clear(); // 到这步仍未真正删除所有拥有的资源
role.Update(); // 更新角色信息,真正实施从数据表删除记录。
Console.WriteLine(role.Resources.Count);
}
/// <summary>
/// 测试给角色从无到有地添加资源的作用
/// </summary>
[Test]
public void RoleAddResourceTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
Role role = Role.Find( 3 ); // 本来就有三个资源
Console.WriteLine(role.Resources.Count);
Role role4 = Role.Find( 4 ); // 本来没有资源
Console.WriteLine(role4.Resources.Count);
role4.Resources.Add(Resource.Find( 2 )); // 添加一个资源,未真正添加到数据表
Console.WriteLine(role4.Resources.Count);
role4.Update(); // 真正添加到数据表
/*
控制台输出结果:
------ Test started: Assembly: StephenCat.WebFolder.dll ------
3
0
1
1 passed, 0 failed, 0 skipped, took 2.23 seconds.
*/
}
/// <summary>
/// 测试更新角色所拥有的资源
/// </summary>
[Test]
public void RoleUpdateResourceTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
Role role = Role.Find( 3 ); // 本来有三个资源
Console.WriteLine(role.Resources.Count);
role.Resources.Clear(); // 尝试删除全部所拥有的资源
role.Resources.Add(Resource.Find( 1 )); // 添加一个资源
Console.WriteLine(role.Resources.Count);
role.Update(); // 更新到数据表
/*
控制台输出结果:
------ Test started: Assembly: StephenCat.WebFolder.dll ------
3
1
1 passed, 0 failed, 0 skipped, took 2.27 seconds.
*/
}
/// <summary>
/// 测试角色是否拥有某个资源,使用 ActiveRecord 本来的方法
/// </summary>
[Test]
public void RoleHasResourceARTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
Role role = Role.Find( 3 );
// 遍历角色所拥有的资源
foreach (Resource res in role.Resources)
{
Console.WriteLine(res.Id);
}
/*
控制台输出:
1
2
3
5
*/
Console.WriteLine(role.Resources.Contains(Resource.Find( 2 )));
// 由于 GetHasCode() 的值不同,所以返回 False。
// 因此不能使用 Contains 方法直接判断对象是否相等。
// 通过判断对象的属性是否相等来判断角色是否包含一个资源,这样才会返回 True。
foreach (Resource res in role.Resources)
{
if (res.Id == Resource.Find( 2 ).Id)
{
Console.WriteLine( true );
break ;
}
}
// 比较 stupid,最终还是要面向数据库而非面向对象。
// 要面向对象的话,只能自己在每个 domain 类里面手写方法了。
}
[Test]
public void RoleRemoveResourceTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
Role role = Role.Find( 3 );
role.Resources.Remove(Resource.Find( 2 ));
role.Update();
// 这样也是不能真正删除指定的资源的,只能通过循环检查删除了
foreach (Resource res in role.Resources)
{
if (res.Id == Resource.Find( 2 ).Id)
{
role.Resources.Remove(res);
break ;
}
}
role.Update(); // 这样才真正删除了。
}
}
}
using System.Collections; // 用于 IList 操作
using NUnit.Framework; // 用于单元测试
using System.Reflection;
using Castle.ActiveRecord.Framework.Config; // 用于读取内嵌的 Castle AR 配置
using Castle.ActiveRecord; // 用于启动 AR 特性
using StephenCat.WebFolder.Domain; // 领域对象
namespace StephenCat.WebFolder._TestUnitCase
{
/// <summary>
/// RoleTest 的摘要说明。
/// </summary>
[TestFixture]
public class RoleTest
{
public RoleTest()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
/// <summary>
/// 测试创建一个角色
/// </summary>
[Test]
public void RoleCreateTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
// using(new SessionScope())
// {
Role role = new Role();
role.Name = " sysadmin " ;
role.Description = " administrator1234 " ;
role.Save();
// }
}
/// <summary>
/// 测试不清除原来记录的情况下向角色添加三个资源(循环 n 次测试)。
/// </summary>
[Test]
public void RoleAddAgainResourceTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
Role role = Role.Find( 3 );
role.Resources.Add(Resource.Find( 2 ));
role.Resources.Add(Resource.Find( 3 ));
role.Resources.Add(Resource.Find( 5 ));
role.Update(); // 循环三次会出现九条记录。AR 不会考虑仅仅保留唯一记录。
/*
* 控制台输出:
------ Test started: Assembly: StephenCat.WebFolder.dll ------
1 passed, 0 failed, 0 skipped, took 2.27 seconds.
*/
}
/// <summary>
/// 测试删除所有角色所拥有的资源
/// </summary>
[Test]
public void RoleRemoveAllResourceTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
Role role = Role.Find( 3 );
role.Resources.Clear(); // 到这步仍未真正删除所有拥有的资源
role.Update(); // 更新角色信息,真正实施从数据表删除记录。
Console.WriteLine(role.Resources.Count);
}
/// <summary>
/// 测试给角色从无到有地添加资源的作用
/// </summary>
[Test]
public void RoleAddResourceTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
Role role = Role.Find( 3 ); // 本来就有三个资源
Console.WriteLine(role.Resources.Count);
Role role4 = Role.Find( 4 ); // 本来没有资源
Console.WriteLine(role4.Resources.Count);
role4.Resources.Add(Resource.Find( 2 )); // 添加一个资源,未真正添加到数据表
Console.WriteLine(role4.Resources.Count);
role4.Update(); // 真正添加到数据表
/*
控制台输出结果:
------ Test started: Assembly: StephenCat.WebFolder.dll ------
3
0
1
1 passed, 0 failed, 0 skipped, took 2.23 seconds.
*/
}
/// <summary>
/// 测试更新角色所拥有的资源
/// </summary>
[Test]
public void RoleUpdateResourceTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
Role role = Role.Find( 3 ); // 本来有三个资源
Console.WriteLine(role.Resources.Count);
role.Resources.Clear(); // 尝试删除全部所拥有的资源
role.Resources.Add(Resource.Find( 1 )); // 添加一个资源
Console.WriteLine(role.Resources.Count);
role.Update(); // 更新到数据表
/*
控制台输出结果:
------ Test started: Assembly: StephenCat.WebFolder.dll ------
3
1
1 passed, 0 failed, 0 skipped, took 2.27 seconds.
*/
}
/// <summary>
/// 测试角色是否拥有某个资源,使用 ActiveRecord 本来的方法
/// </summary>
[Test]
public void RoleHasResourceARTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
Role role = Role.Find( 3 );
// 遍历角色所拥有的资源
foreach (Resource res in role.Resources)
{
Console.WriteLine(res.Id);
}
/*
控制台输出:
1
2
3
5
*/
Console.WriteLine(role.Resources.Contains(Resource.Find( 2 )));
// 由于 GetHasCode() 的值不同,所以返回 False。
// 因此不能使用 Contains 方法直接判断对象是否相等。
// 通过判断对象的属性是否相等来判断角色是否包含一个资源,这样才会返回 True。
foreach (Resource res in role.Resources)
{
if (res.Id == Resource.Find( 2 ).Id)
{
Console.WriteLine( true );
break ;
}
}
// 比较 stupid,最终还是要面向数据库而非面向对象。
// 要面向对象的话,只能自己在每个 domain 类里面手写方法了。
}
[Test]
public void RoleRemoveResourceTest()
{
Assembly assembly = typeof (Account).Assembly;
XmlConfigurationSource src = new XmlConfigurationSource(assembly.GetManifestResourceStream( " StephenCat.WebFolder.Domain.ActiveRecord.config " ));
ActiveRecordStarter.Initialize( src, typeof (Role), typeof (Resource) );
// 注意:由于存在关联,这里要初始化两个实体。
// 否则会抛出 unmapped: Resource 的 Exception。
Role role = Role.Find( 3 );
role.Resources.Remove(Resource.Find( 2 ));
role.Update();
// 这样也是不能真正删除指定的资源的,只能通过循环检查删除了
foreach (Resource res in role.Resources)
{
if (res.Id == Resource.Find( 2 ).Id)
{
role.Resources.Remove(res);
break ;
}
}
role.Update(); // 这样才真正删除了。
}
}
}
小结
Castle ActiveRecord 只是把数据表的一行数据映射为一个 .NET 类,把多行数据映射为 Array 数组,数组的元素是 .NET 类。尽管 AR 通过 ActiveRecordBase 类也提供了一些 DAO 应该有的方法,但仍然有某些方法需要自己手工编写。Castle AR 并没有把对象和关系绝对领域化,领域业务方法甚至某些 DAO 方法仍需要自己编写,因此 Castle AR 在封装了 NHibernate 之后也只是完成了对象关系和数据之间的映射工作而已,也仅此而已