NFramework开源AOP框架设计文档
1.1 ITransaction接口
用于事务控制的接口,接口方法如下表:
方法名称 |
方法说明 |
BeginTransaction(+2次重载) |
开始事务 |
CommitTransaction |
递交事务 |
RollbackTransaction |
回滚事务 |
1.2 IDBUtil接口
用于数据库访问的接口。通过工厂方法创建该接口的实例,实现动态数据库的调用。IDBUtil变相的实现了ADO.NET的IDbCommand接口,因此只要您熟悉IDbCommand接口方法,您就可以很容易的使用实现了IDBUtil接口的方法,具体方法如下表:
方法名称 |
方法说明 |
ExecuteNonQuery(+4次重载) |
对连接执行 Transact-SQL 语句并返回受影响的行数 |
ExecuteScalar(+2次重载) |
执行查询,并返回查询所返回的结果集中第一行的第一列。忽略额外的列或行。 |
GetDataTable(+4次重载) |
获取数据集 |
1.3 AccessDBUtil类
用于访问Access数据库的类。AccessDBUtil类继承了ITransaction、IDBUtil接口,因此当根据数据库类型实例化ITransaction或IDBUtil接口时,实际上实例化本类,从而封装客户代码对不同数据库的访问功能。AccessDBUtil类的具体方法如下表:
方法名称 |
方法说明 |
BeginTransaction(+2次重载) |
开始事务 |
CommitTransaction |
递交事务 |
RollbackTransaction |
回滚事务 |
ExecuteNonQuery(+4次重载) |
对连接执行 Transact-SQL 语句并返回受影响的行数 |
ExecuteScalar(+2次重载) |
执行查询,并返回查询所返回的结果集中第一行的第一列。忽略额外的列或行。 |
GetDataTable(+4次重载) |
获取数据集 |
1.4 SqlServerDBUtil类
用于访问Sql Server数据库的类。同AccessDBUtil类。
方法名称 |
方法说明 |
BeginTransaction(+2次重载) |
开始事务 |
CommitTransaction |
递交事务 |
RollbackTransaction |
回滚事务 |
ExecuteNonQuery(+4次重载) |
对连接执行 Transact-SQL 语句并返回受影响的行数 |
ExecuteScalar(+2次重载) |
执行查询,并返回查询所返回的结果集中第一行的第一列。忽略额外的列或行。 |
GetDataTable(+4次重载) |
获取数据集 |
1.5 OracleDBUtil类
用于访问Oracle数据库的类。同AccessDBUtil类。
方法名称 |
方法说明 |
BeginTransaction(+2次重载) |
开始事务 |
CommitTransaction |
递交事务 |
RollbackTransaction |
回滚事务 |
ExecuteNonQuery(+4次重载) |
对连接执行 Transact-SQL 语句并返回受影响的行数 |
ExecuteScalar(+2次重载) |
执行查询,并返回查询所返回的结果集中第一行的第一列。忽略额外的列或行。 |
GetDataTable(+4次重载) |
获取数据集 |
1.6 Connector类
Connector类采用单件模式创建,用于从Web.Config文件中获取数据库的连接信息。
方法/属性名称 |
方法/属性说明 |
GetInstance方法 |
取得单件实例 |
DataBaseType属性 |
数据库类型 |
DataBaseConnection属性 |
数据库连接字符串 |
具体配置信息如下:
<appSettings>
<!--数据库连接字符串-->
<addkey="DBConnection"value=""/>
<!--数据库可选类型:Sql,Oracle,Access-->
<addkey="DBType"value="Access"/>
</appSettings>
1.7 Factory类
用于实现工厂方法的类。通过Factory类获取ITransaction、IDBUtil接口的实例,从而实现对不同数据库的封装。
方法名称 |
方法说明 |
GetInstance(+2次重载) |
取得工厂实例 |
1.8 Transaction类
用于提供事务的类。具体方法如下表:
方法/属性名称 |
方法/属性说明 |
BeginTransaction方法 |
开始事务 |
CommitTransaction方法 |
递交事务 |
RollbackTransaction方法 |
回滚事务 |
Transaction类用于方便、灵活的控制同一业务层方法内的事务,如需在不同业务层之间、不同方法之间控制事务,请使用TransactionScope类。
1.9 TransactionScope类
用于提供事务的基类。具体方法如下表:
方法/属性名称 |
方法/属性说明 |
BeginTransaction方法 |
开始事务 |
CommitTransaction方法 |
递交事务 |
RollbackTransaction方法 |
回滚事务 |
SynchronizeTransaction方法 |
同步事务 |
IsSuppressed属性 |
指示是否临时挂起事务,挂起的事务不会执行Commit、Rollback方法 |
TransactionScope类是框架的重要类之一,用于提供对事务的支持。用户的业务逻辑层代码只需继承此类就可以实现自动事务的功能。
SynchronizeTransaction方法用于同步不同业务层的事务。举例来说:A业务用于更新库存,其有自己的事务。B业务用于记录日志,也有自己独立的事务。但当A调用B时,就要保证A和B共用同一事务,此时就用到了本方法,其实质也就是传递了一个ITransaction类型的参数。另外,如果同一个BLL层的事务有如下情况,比如说:方法A调用了方法B,A有事务控制,B也有事务控制,那么也要保证A与B使用同一个事务,此时就用到了IsSuppressed属性,将IsSuppressed属性设置为真,则不会执行递交事务,回滚事务方法,当需要执行事务时,再将其值设置为假即可。因此,从上面的说明可以看出,SynchronizeTransaction与IsSuppressed都是用于做事务控制的,而二者的区别是前者用于不同BLL层同步事务的处理,而后者用于同一BLL层内不同方法间的同步事务处理。
l SynchronizeTransaction方法的示例代码如下:
///<summary>
///用于库存调整的业务逻辑类
///继承于TransactionScope类,以提供事务的控制
///</summary>
public class StockAdjustBLL : TransactionScope
{
///<summary>
///新建库存调整单
///</summary>
///<returns>生成的主键ID</returns>
public string Insert()
{
// DAL层数据库访问方法类
StockAdjustDAL dal = new StockAdjustDAL();
try
{
// 调用DBTransaction 类的BeginTransaction方法启动事务
ITransaction trans = this.BeginTransaction();
// 将事务参数赋予数据访问层
dal.SynchronizeTransaction(trans);
// 注意:第一个访问事务
StockAdjustEntity stockadjust = new StockAdjustEntity();
// 插入库存调整表数据
dal.InsertEntity(stockadjust);
// 注意:第二个访问事务
StockEntity stock = new StockEntity();
StockBLL stockBll = new StockBLL();
// 重要方法,保证在不同的BLL层在同一事务内运行
stockBll.SynchronizeTransaction(trans);
// 更新库存
stockBll.Update(stock);
// 注意:第三个访问事务
// 写库存操作日志
StockLogEntity log = new StockLogEntity();
StockLogBLL logBll = new StockLogBLL();
// 重要方法,保证在不同的BLL层在同一事务内运行
logBll.SynchronizeTransaction(trans);
// 写库存操作日志
logBll.Insert(log);
// 最后递交事务
this.CommitTransaction();
}
catch (Exception ex)
{
// 出错时回滚事务
this.RollbackTransaction();
ErrorHandler.HandleError(ex);
}
// 返回主键ID
return stockadjust.StockAdjustID;
}
l IsSuppressed方法的示例代码
同时下面的这个示例也说明了不同BLL层,相同BLL层事务处理的方法。
///<summary>
///审批采购单
/// 1=未审批,2=审批通过,3=审批未通过,4=部分审批通过
///</summary>
///<param name="purchaseID">采购单ID</param>
public void Approve(string purchaseID)
{
PurchaseDAL dal = new PurchaseDAL();
PurchaseEntity purchase;
try
{
ITransaction trans = this.BeginTransaction();
// 重要方法,保证在同一事务内运行
dal.SynchronizeTransaction(trans);
// 由于在本类中GetEntity方法也使用了事务
// 所以此处要挂起GetEntity事务的执行
this.IsSuppressed = true;
// 获取采购信息,此操作会自动使用当前事务
purchase = GetEntity(purchaseID);
purchase.PurchaseID = purchaseID;
purchase.Status = "2";
purchase.ApproveID = WebBasePage.GetCurrentSession().UserID;
purchase.ApproveDate = DateTime.Now;
dal.UpdateEntity(purchase);
// 审批同意后更新库存
StockEntity stock = null;
StockEntities stocks;
StockBLL stockBll = new StockBLL();
// 重要方法,保证在同一事务内运行
stockBll.SynchronizeTransaction(trans);
// 根据product和type信息获取库存信息以便于记录日志
QueryEntity query = new QueryEntity();
query.BuildQueryWhere("Product", CompareTypeEnum.Equal, purchase.ProductID, LogicTypeEnum.And);
query.BuildQueryWhere("TypeID", CompareTypeEnum.Equal, purchase.StockTypeID, LogicTypeEnum.And);
stocks = stockBll.GetEntities(query);
if (stocks.Count <= 0)
{
stock = new StockEntity();
stock.ProductID = purchase.ProductID;
stock.StockTypeID = purchase.StockTypeID;
stock.StockNum = purchase.PurchaseNum;
stock.KeepNum = 0;
stock.WayNum = 0;
stock.SafeNum = 0;
stock.UserID = purchase.ApproveID;
stock.OperateTime = purchase.ApproveDate;
stockBll.Insert(stock);
}
else if (stocks.Count > 1)
{
// 抛出业务逻辑异常
ErrorHandler.ThrowBusinessError("库存中多个同种产品,请检查!");
}
else
{
stock = stocks.GetItem(0);
stock.StockNum = stock.StockNum + purchase.PurchaseNum;
stockBll.Update(stock);
}
// 写库存操作日志
StockLogEntity log = new StockLogEntity();
StockLogBLL logBll = new StockLogBLL();
// 重要方法,保证在同一事务内运行
logBll.SynchronizeTransaction(trans);
log.ProductID = purchase.ProductID;
log.StockTypeID = purchase.StockTypeID;
log.StockOptNum = purchase.PurchaseNum;
log.KeepOptNum = 0;
log.WayOptNum = 0;
log.StockNum = stock.StockNum;
log.KeepNum = stock.KeepNum;
log.WayNum = stock.WayNum;
log.Remark = "采购";
log.ObjNO = purchaseID;
log.OperateTime = DateTime.Now;
log.UserID = purchase.ApproveID;
logBll.Insert(log);
// 恢复事务的执行
this.IsSuppressed = false;
this.CommitTransaction();
}
catch (Exception ex)
{
this.RollbackTransaction();
ErrorHandler.HandleError(ex);
}
}
1.10 TransactionService类
用于提供COM+事务的基类。
方法名称 |
方法说明 |
CompleteTx |
递交事务 |
AbortTx |
回滚事务 |
TransactionService类是框架的重要类之一,用于提供对分布式事务的支持。由于本功能实际上是使用了COM+提供的事务控制功能,因此必须将使用此类的程序集部署到COM+运行环境中。配置COM+应用的方法如下:
1. 使用sn.exe工具为程序集生成强名称
2. 将强名称程序集部署到全局程序集缓存
gacutil -nologo -i MyAssemble.dll
3. 将强名称程序集部署到COM+中
regsvcs -nologo MyAssemble.dll
从COM+中卸载的例子:
1. 先从COM+中卸载
regsvcs -nologo -u MyAssemble.dll
2. 从全局程序集缓存中卸载
gacutil -nologo -u MyAssemble.dll
关于COM+的具体信息,请参见MSDN。
1.11 Access类
实际的数据访问基类,用户的DAL层要从此类继承。
方法名称 |
方法说明 |
GetDBUtil |
获取指定数据库访问对象 |
SynchronizeTransaction |
同步事务 |
GetGuid |
获取GUID |
GetEntity |
获取实体 |
GetEntitiesCount |
获取实体个数 |
GetEntities |
获取实体集 |
InsertEntity |
新增 |
UpdateEntity |
更新 |
DeleteEntity |
删除 |
GetSequence |
获取序列值(目前只针对Oracle) |
1.12 SqlBuilder类
用于根据实体生成SQL语句的类。框架的重要类之一。
方法名称 |
方法说明 |
BuildCondiction |
获取完整的条件语句(where、group、order) |
BuildSqlWhere |
生成WHERE条件语句 |
BuildSqlGroup |
生成Sql分组语句 |
BuildSqlOrder |
生成Sql排序语句 |
BuildSqlSelect |
生成SELECT语句 |
BuildSqlInsert |
生成Insert语句,忽略实体中的null值字段 |
BuildSqlUpdate |
生成Update语句,忽略实体中的null值字段 |
BuildSqlDelete |
生成DELETE语句,忽略实体中的null值字段 |
BuildParameters |
生成参数实体,忽略实体中的null值字段 |
BuildParamsSqlInsert |
生成参数化的Insert语句,忽略实体中的null值字段 |
BuildParamsSqlUpdate |
生成参数化的Update语句,忽略实体中的null值字段 |
PreHandleComma |
处理单引号的问题 |
PreHandleSql |
预处理Sql语句,主要处理了LIKE条件的保留字符,如:%、_、[、^ |
1.13 BaseEntities类
所有实体集合类的基类,提供了序列化、索引器,枚举器、DataTable转换功能。
方法名称 |
方法说明 |
ConvertTo |
将实体集合转换成DataTable形式 |
ConvertFrom |
通过实体映射的字段名将DataTable值解析成实体集合 |
Parse |
通过实体映射的属性名将DataTable值解析成实体集合 |
GetItem |
通过索引获取 |
SetItem |
设置实体 |
Add |
增加 |
Remove |
通过索引移除 |
Clear |
全部移除 |
Count |
获取个数 |
1.14 BaseEntity类
所有实体类的基类,提供获取实体O/R Mapping相关信息、DataTable转换功能。
方法名称 |
方法说明 |
ConvertTo |
将实体集合转换成DataTable形式 |
ConvertFrom |
通过实体映射的字段名将DataTable值解析成实体集合 |
Parse |
通过实体映射的属性名将DataTable值解析成实体集合 |
GetTableName(+2次重载) |
获取实体映射的表名 |
GetPropertyName |
获取数据库字段名对应的属性名,如果找不到对应的属性名则返回传入的字段名 |
GetPropertyNames |
获取实体的所有属性名的数组形式 |
GetFieldName |
获取实体映射的字段名,如果找不到对应的字段名则返回传入的属性名 |
GetFieldNames |
获取实体映射的字段名所有字段名的数组形式 |
GetPropertyValue |
获取实体的属性值,如果指定的属性名不存在则返回null |
GetDataType |
获取实体映射的数据类型,如果指定的属性名不存在则使用字段名再次进行查询,如果还不存在,则返回DataTypeEnum.Default,建议使用属性名进行获取以符合O/R Mappgin的思想 |
IsPK |
获取实体映射的字段是否是主键,如果指定的属性名不存在则返回false |
IsSelected |
获取实体映射的字段是否可以Select,如果指定的属性名不存在则返回false |
IsInserted |
获取实体映射的字段是否可以Insert,如果指定的属性名不存在则返回false |
IsUpdated |
获取实体映射的字段是否可以Update,如果指定的属性名不存在则返回false |
1.15 QueryEntities类
用于查询的实体集合类,即容器类。此类支持索引器、枚举器功能。
方法名称 |
方法说明 |
GetItem |
通过索引获取 |
SetItem |
设置实体 |
Add |
增加 |
Remove |
通过索引移除 |
Clear |
全部移除 |
Count |
获取个数 |
1.16 QueryEntity类
用于查询的实体类。QueryEntity类在传递查询条件时十分有用,可以自动生成相对应的SQL条件语句,并且在参数类型方面也可以根据实体映射自动识别参数类型,长度等信息。QueryEntity类主要属性如下表:
属性名称 |
属性说明 |
PageIndex |
要查询的页数 |
PageSize |
查询页显示的记录数 |
RecordCount |
总记录数 |
WhereEntities |
过滤条件 |
GroupEntities |
分组条件 |
OrderEntities |
排序条件 |
1.17 QueryWhereEntities类
查询条件容器类,功能同QueryEntities类。
1.18 QueryWhereEntity类
查询条件实体类。具体属性如下表:
属性名称 |
属性说明 |
CompareType |
比较操作符 |
LogicType |
逻辑操作符 |
BracketType |
括号类型 |
FieldName |
字段名,可以属性名,也可以实际的数据表字段名,在生成条件时会自动进行匹配 |
DataType |
字段类型,对于没有进行O/R Mapping设置的实体类,必须指定实际的类型 |
FieldValue |
字段值 |
1.19 QueryGroupEntities类
分组条件容器类,功能同QueryEntities类。
1.20 QueryGroupEntity类
分组条件实体类。具体属性如下表:
属性名称 |
属性说明 |
FieldName |
字段名,可以属性名,也可以实际的数据表字段名,在生成条件时会自动进行匹配 |
1.21 QueryOrderEntities类
排序条件容器类,功能同QueryEntities类。
1.22 QueryOrderEntity类
排序条件实体类。具体属性如下表:
属性名称 |
属性说明 |
FieldName |
字段名,可以属性名,也可以实际的数据表字段名,在生成条件时会自动进行匹配 |
OrderType |
排序方式 |
1.23 ParameterEntities类
参数实体容器类,功能同QueryEntities类。
1.24 ParameterEntity类
参数实体类。具体属性如下表:
属性名称 |
属性说明 |
ParameterName |
参数名,可以属性名,也可以实际的数据表字段名,在生成参数时会自动进行匹配 |
ParameterValue |
参数值 |
ParameterType |
对于没有进行O/R Mapping设置的实体类,必须指定实际的类型 |
ParameterDirection |
参数方向,可以是输入参数、输入输出参数、输出参数、返回值参数 |
1.25 Error类
自定义异常类,继承于ApplicationException。用于扩展异常信息。
属性名称 |
属性说明 |
ErrorID |
异常ID |
ErrorType |
异常类型 |
MachineName |
异常所在机器名 |
ErrorTime |
异常发成时间 |
SqlCommand |
引发异常的SQL语句 |
UserID |
引发异常的用户ID |
VisitPage |
引发异常的页面 |
Description |
自定义的异常详细描述信息 |
1.26 ErrorHandler类
用于显示的处理的自定义异常的类。
方法名称 |
方法说明 |
HandleError |
处理异常,并根据配置信息决定是否记录日志 |
ThrowBusinessError |
抛出业务逻辑异常 |
ThrowTechError |
抛出技术异常 |
1.27 Logger类
日志处理类。配置信息如下:
<!--是否记录日志-->
<addkey="LogEnabled"value="true|false"/>
<!--日志文件名称及位置-->
<addkey="LogFile"value="c:""log.txt"/>
<!--日志文件的最大尺寸-->
<addkey="LogMaxSize"value="10M"/>
<!--是否在页面上显示详细的日志信息-->
<addkey="ShowErrors"value="true|false"/>
方法名称 |
方法说明 |
WriteLog |
记录日志 |
1.28 ORMapingAttribute类
O/R Mapping实现类,框架的重要类之一。属性如下表:
属性名称 |
属性说明 |
TableName |
表名 |
FieldName |
字段名 |
IsPK |
是否是主键 |
IsSelected |
Select时是否包含 |
IsInserted |
Insert时是否包含 |
IsUpdated |
Update时是否包含 |
RelationName |
表之间的关联信息,可以是join关联,也可是子查询关联 |
1.29 WebBasePage类
Web页面基类,提供Session控制、权限检测、错误处理等常用功能。
方法名称 |
方法说明 |
GetCurrentSession |
获取当前会话对象 |
IsLogin |
判断是否已登录 |
LogOut |
注销 |
OnLoad |
重载登录方法,用于判断是否已登录 |
OnError |
重载出错时的处理方法,以支持统一的异常处理方式、日志记录方式 |
MessageBox(+3次重载) |
显示具有指定文本的消息框 |
GetAppPath |
获取当前WEB应用程序的绝对路径 |
GetCurrentPage |
获取当前访问的页面 |
OneClickButton(+1次重载) |
使得服务端Button在一次Postback中只能点击一次 |
1.30 WebSession类
会话对象实体类,属性说明如下表:
属性名称 |
属性说明 |
WebSessionID |
会话ID |
UserID |
用户ID |
UserName |
用户姓名 |
LoginName |
用户登录名 |
OrganID |
组织ID |
OrganName |
组织名称 |
DeptID |
部门ID |
DeptName |
部门名称 |
RoleID |
角色ID |
RoleName |
角色名称 |
CountryCode |
国家代码 |
LanguageCode |
语言代码 |