架构是什么?架构就是总结
(二)
作者:长江支流
关 键 字:架构、三层结构、多层架构
日 期:2007-04-12
文章摘要
通过一个实例代码,通过遇到问题解决问题的不断反复,得出:在实践基础上,不断分析并总结,引申出架构要解决的一些问题。
正文
前篇说了,架构就是实践。这里进一步说明,架构就是总结。
先来看一段代码,想想它是来实现什么的?
public class EntityTest:WebMIS.Data.EntityAccess.DBEntity
{
private int _ID = -1;
private string _Name = "test";
public int ID
{
get{return _ID;}
set{_ID=value;}
}
public string Name
{
get{return _Name;}
set{_Name=value;}
}
public EntityTest():base("TableNameOfEntityTest","ID"){}
public override IList GetFields()
{
return new string[]{"ID","Name"};
}
public override IList GetFieldValues()
{
return new object[]{_ID,_Name};
}
public override IList GetPrimaryKeyValues()
{
return new string[]{"ID"};
}
public override void LoadFrom(System.Data.DataRow entityDataRow)
{
_ID = int.Parse(entityDataRow["ID"].ToString());
_Name = entityDataRow["Name"].ToString();
}
}
public class EntityTestManagement:WebMIS.Data.EntityAccess.EntityAccess
{
public EntityTestManagement(EntityTest entity):base(entity){}
protected override WebMIS.Data.EntityAccess.IExeSql DoReturnDataAccessInstance()
{
return null; //只要实现IExeSql并返回,即可完成跨数据库操作
}
}
也许大家看出来了,EntityTest完成一个实体定义,一般来说对应于数据库表的字段。EntityTest继承于WebMIS.Data.EntityAccess.DBEntity,其实是实现了IEntityMap接口。
不写一个SQL语句,不再多写一行程序,就实现数据的增、删、改、查,这就是这样做的目的。 那么,如何达到这个目的呢?
只要把实现了IEntityMap接口的实体对象,作为WebMIS.Data.EntityAccess.EntityAccess的构造函数参数即可达到目的。
为什么会这样?这其实就是总结的结果。
因为我在做数据处理的时候,定义了实体,每个实体操作总是要写Insert、Update、Delete、FillByPK...这类的方法,而且总是会用到表的字段。这样重复做了几次之后,想想是不是应该抽象一下,并把它重构。于是发现了规律性,把Insert、Update、Delete、FillByPK提到基类WebMIS.Data.EntityAccess.EntityAccess中。
提到基类中后,问题又来了,Insert、Update、Delete、FillByPK用到的表、字段它们从何来?于是,将它们抽象出来,定义到接口中,于是IEntityMap接口诞生了,从中可以找到用到的表和字段,于是就可以同它们动态的生成需要的SQL语句。
这样,问题又来了,是不是执行SQL语句的数据库连接数据访问层就在EntityAccess中实现。答案是否定的,原因如下:
1>偶合性
为了让EntityAccess独立,放到哪里就运行到哪里,所以需要把真正执行SQL语句的代码独立出来。
2>跨数据访问
如果写死了,就可能只为一种数据库服务限制死,所以需要把真正执行SQL语句的代码独立出来,这样,谁提供数据执行应适应谁的数据库。
3>灵活性
只要传个SQL给接口,就可以出结果,非常灵活。而实现接口的数据处理,可以直接执行SQL,也可以根据SQL传的参数与值,转成带命令参数的形式执行。
为了防止注入式攻击和非法字符引发错误,建议采用参数形式解释执行SQL语句。
于是,定义 IExeSql 接口。
using System;
namespace WebMIS.Data.EntityAccess
{
/// <summary>
/// 执行带参的SQL接口,如例如ExecuteSql("Delete From 表1 Where aa=参数1 And bb=参数2",new string[]{"参数1","参数2"},new string[]{"ax","bx"})。
/// </summary>
public interface IExeSql
{
/// <summary>
/// 执行单个带参数的操作型SQL,并返回受影响的行数。
/// 例如ExecuteSql("Delete From 表1 Where aa=参数1 And bb=参数2",new string[]{"参数1","参数2"},new string[]{"ax","bx"})。
/// </summary>
/// <param name="p_strSQL">带参数的SQL</param>
/// <param name="p_strParams">参数列表</param>
/// <param name="p_objValues">参数对应的值</param>
/// <returns>返回受影响的行数,不成功返回-1</returns>
int ExecuteSql(string p_strSQL,System.Collections.IList p_strParams,System.Collections.IList p_objValues);
/// <summary>
/// 执行单个带参数的选择型SQL,并返回它的记录集。
/// 例如CreateDataSet("Select * From 表1 Where aa=参数1 And bb=参数2",new string[]{"参数1","参数2"},new string[]{"ax","bx"})。
/// </summary>
/// <param name="p_strSQL">带参数的SQL</param>
/// <param name="p_strParams">参数列表</param>
/// <param name="p_objValues">参数对应的值</param>
/// <returns>返回受影响的行数,不成功返回-1</returns>
System.Data.DataSet CreateDataSet(string p_strSQL,System.Collections.IList p_strParams,System.Collections.IList p_objValues);
}
}//End Namespace
总结:
架构,决不是仅仅对数据的增、删、改、查。它涉及到方方面面,通过增、删、改、查,便可以引出很多问题。
例如:
1>错误处理
出现错误怎么办,难道就try{...}catch{}过去就OK了吗?这其实是对用户极不负责任的做法,也给自己开发调试以及团队合作带来极大的麻烦。所以需要引入错误处理机制。
2>日志处理
错误是怎么出现的?为什么出现?谁上了机?谁非法操作...,这些记录于日志中。
3>各层间通信
典型的三层应用,表现层--业务层--数据层,它们之间是怎么联系的,谁作为数据传输的纽带与载体?
4>缓存处理
对象是否要持久?怎样做到高速访问?缓存同步如何处理?
5>权限处理
是小型应用还是企业开发?权限控制在什么程度?除了功能控制外,还需要操作范围控制吗?还需要数据控制呢?
6>事务处理
/*
* 现有如下情况:
*
* 如处理一个业务,会启动事务,并且,还会调用对象A、B。
* 而对象A、B作为独立对象运行时,也会有事务处理。
* 业务X:
* BeginTrans
* ...
* 对象A:
*
* BeginTrans
* Master
* ...
* Detail
* ...
* CommitTrans/RollbackTrans
*
* 对象B:
*
* BeginTrans
* Master
* ...
* Detail
* ...
* CommitTrans/RollbackTrans
* ...
* CommitTrans/RollbackTrans
*
* 因为有的数据库不支持嵌套事务,如Oracle就是。
*
* 如何保存不出现错误,即在业务X启动事务里,调用单据对象,使之不再启动同一数据库的事务。
*
*
如果在企业级软件或软件整合应用中,不在同一数据库,事务又是如何处理?
是使用企业服务的MSTS,让每个数据操作的类继承于System.EnterpriseServices.ServicedComponent?还是自己实现?还是使用VS2005提供的事务处理机制?
。。。
这些,都需要根据实际情况处理。根据实践,不但总结,达到创新,最终实现适合自己的应用。
本文来源:CSDN上的长江支流Blog:
http://blog.csdn.net/flygoldfish
声明:本文版权为周方勇所有,如需转载,请保留完整的内容及出处。
相关搜索: