数据访问组件是一组通用的访问数据库的代码在所有项目中都可以用一般不需要修改本节使用的是Microsoft提供的数据访问助手其封装很严密且应用简单
首先要先添加一个类并命名为SqlHelper系统会提示是否将类放在App_Code文件夹中此时一定要选择是因为放在此文件夹下系统会自动进行编译程序员就可以直接使用无需另外编译了
SqlHelper的目的是从数据库获得信息或将信息保存到数据库本实例的SqlHelper主要功能如下
()执行不返回数据的TSql命令例如修改会员卡信息添加会员资料等
()返回一个字段的TSql命令例如获取会员卡类型的积分规则
()返回一组数据例如获取会员资料获取所有会员卡类型等
()缓存参数列表在执行一条语句时可能有多个参数为了提高速度将参数缓存
()读取缓存的参数
下面用图表的方式描述SqlHelper类的功能如图所示
在SqlHelper类中添加数据库处理代码如下
//编号
usingSystem;
usingSystemData;
usingSystemConfiguration;
usingSystemWeb;
usingSystemWebSecurity;
usingSystemCollections;
usingSystemDataSqlClient;
//编号
/**////<summary>
///数据库的通用访问代码
///此类为抽象类不允许实例化在应用时直接调用即可
///</summary>
publicabstractclassSqlHelper
{
//获取数据库连接字符串其属于静态变量且只读项目中所有文档可以直接使用但不能修改
//编号
publicstaticreadonlystringConnectionStringLocalTransaction=
ConfigurationManagerConnectionStrings[connstring]ConnectionString;
//哈希表用来存储缓存的参数信息哈希表可以存储任意类型的参数
//编号
privatestaticHashtableparmCache=HashtableSynchronized(newHashtable());//编号
/**////<summary>
///执行一个不需要返回值的SqlCommand命令通过指定专用的连接字符串
///使用参数数组形式提供参数列表
///</summary>
///<remarks>
///使用示例
///intresult=ExecuteNonQuery(connStringCommandTypeStoredProcedure
///PublishOrdersnewSqlParameter(@prodid));
///</remarks>
///<paramname=connectionString>一个有效的数据库连接字符串</param>
///<paramname=commandType>SqlCommand命令类型(存储过程TSQL语句等等)
///</param>
///<paramname=commandText>存储过程的名字或者TSQL语句</param>
///<paramname=commandParameters>以数组形式提供SqlCommand命令中用到的参数列表
///</param>
///<returns>返回一个数值表示此SqlCommand命令执行后影响的行数</returns>
//编号
publicstaticintExecuteNonQuery(stringconnectionStringCommandTypecmdType
stringcmdTextparamsSqlParameter[]commandParameters)
{
SqlCommandcmd=newSqlCommand();
//编号
using(SqlConnectionconn=newSqlConnection(connectionString))
{
//通过PrePareCommand方法将参数逐个加入到SqlCommand的参数集合中
PrepareCommand(cmdconnnullcmdTypecmdTextcommandParameters);
intval=cmdExecuteNonQuery();
//清空SqlCommand中的参数列表
cmdParametersClear();
//编号
returnval;
}
}
/**////<summary>
///执行一条不返回结果的SqlCommand通过一个已经存在的数据库连接
///使用参数数组提供参数
///</summary>
///<remarks>
///使用示例
///intresult=ExecuteNonQuery(connCommandTypeStoredProcedure
///PublishOrdersnewSqlParameter(@prodid));
///</remarks>
///<paramname=conn>一个现有的数据库连接</param>
///<paramname=commandType>SqlCommand命令类型(存储过程TSQL语句等等)
///</param>
///<paramname=commandText>存储过程的名字或者TSQL语句</param>
///<paramname=commandParameters>以数组形式提供SqlCommand命令中用到的参数列表
///</param>
///<returns>返回一个数值表示此SqlCommand命令执行后影响的行数</returns>
//编号
publicstaticintExecuteNonQuery(SqlConnectionconnectionCommandTypecmdTypestringcmdTextparamsSqlParameter[]commandParameters)
{
SqlCommandcmd=newSqlCommand();
PrepareCommand(cmdconnectionnullcmdTypecmdTextcommandParameters);
intval=cmdExecuteNonQuery();
cmdParametersClear();
returnval;
}
/**////<summary>
///执行一条不返回结果的SqlCommand通过一个已经存在的数据库事物处理
///使用参数数组提供参数
///</summary>
///<remarks>
///使用示例
///intresult=ExecuteNonQuery(transCommandTypeStoredProcedure
///PublishOrdersnewSqlParameter(@prodid));
///</remarks>
///<paramname=trans>一个存在的sql事物处理</param>
///<paramname=commandType>SqlCommand命令类型(存储过程TSQL语句等等)
///</param>
///<paramname=commandText>存储过程的名字或者TSQL语句</param>
///<paramname=commandParameters>以数组形式提供SqlCommand命令中用到的参数列表
///</param>
///<returns>返回一个数值表示此SqlCommand命令执行后影响的行数</returns>
//编号
publicstaticintExecuteNonQuery(SqlTransactiontransCommandTypecmdTypestringcmdTextparamsSqlParameter[]commandParameters)
{
SqlCommandcmd=newSqlCommand();
PrepareCommand(cmdtransConnectiontranscmdTypecmdTextcommandParameters);
intval=cmdExecuteNonQuery();
cmdParametersClear();
returnval;
}
/**////<summary>
///执行一条返回结果集的SqlCommand命令通过专用的连接字符串
///使用参数数组提供参数
///</summary>
///<remarks>
///使用示例
///SqlDataReaderr=ExecuteReader(connStringCommandTypeStoredProcedure
///PublishOrdersnewSqlParameter(@prodid));
///</remarks>
///<paramname=connectionString>一个有效的数据库连接字符串</param>
///<paramname=commandType>SqlCommand命令类型(存储过程TSQL语句等等)
///</param>
///<paramname=commandText>存储过程的名字或者TSQL语句</param>
///<paramname=commandParameters>以数组形式提供SqlCommand命令中用到的参数列表
///</param>
///<returns>返回一个包含结果的SqlDataReader</returns>
publicstaticSqlDataReaderExecuteReader(stringconnectionStringCommandTypecmdTypestringcmdTextparamsSqlParameter[]commandParameters)
{
SqlCommandcmd=newSqlCommand();
SqlConnectionconn=newSqlConnection(connectionString);
//在这里使用try/catch处理是因为如果方法出现异常则SqlDataReader就不存在
//CommandBehaviorCloseConnection的语句就不会执行触发的异常由catch捕获
//关闭数据库连接并通过throw再次引发捕捉到的异常
try
{
PrepareCommand(cmdconnnullcmdTypecmdTextcommandParameters);
SqlDataReaderrdr=cmdExecuteReader(CommandBehaviorCloseConnection);
cmdParametersClear();
returnrdr;
}
catch
{
connClose();
throw;//编号
}
}
/**////<summary>
///执行一条返回第一条记录第一列的SqlCommand命令通过专用的连接字符串
///使用参数数组提供参数
///</summary>
///<remarks>
///使用示例
///Objectobj=ExecuteScalar(connStringCommandTypeStoredProcedure
///PublishOrdersnewSqlParameter(@prodid));
///</remarks>
///<paramname=connectionString>一个有效的数据库连接字符串</param>
///<paramname=commandType>SqlCommand命令类型(存储过程TSQL语句等等)
///</param>
///<paramname=commandText>存储过程的名字或者TSQL语句</param>
///<paramname=commandParameters>以数组形式提供SqlCommand命令中用到的参数列表
///</param>
///<returns>返回一个object类型的数据可以通过ConvertTo{Type}方法转换类型</returns>
publicstaticobjectExecuteScalar(stringconnectionStringCommandTypecmdTypestringcmdTextparamsSqlParameter[]commandParameters)
{
SqlCommandcmd=newSqlCommand();
using(SqlConnectionconnection=newSqlConnection(connectionString))
{
PrepareCommand(cmdconnectionnullcmdTypecmdTextcommandParameters);
objectval=cmdExecuteScalar();
cmdParametersClear();
returnval;
}
}
/**////<summary>
///执行一条返回第一条记录第一列的SqlCommand命令通过已经存在的数据库连接
///使用参数数组提供参数
///</summary>
///<remarks>
///使用示例
///Objectobj=ExecuteScalar(connStringCommandTypeStoredProcedure
///PublishOrdersnewSqlParameter(@prodid));
///</remarks>
///<paramname=conn>一个已经存在的数据库连接</param>
///<paramname=commandType>SqlCommand命令类型(存储过程TSQL语句等等)
///</param>
///<paramname=commandText>存储过程的名字或者TSQL语句</param>
///<paramname=commandParameters>以数组形式提供SqlCommand命令中用到的参数列表
///</param>
///<returns>返回一个object类型的数据可以通过ConvertTo{Type}方法转换类型
///</returns>
publicstaticobjectExecuteScalar(SqlConnectionconnectionCommandTypecmdTypestringcmdTextparamsSqlParameter[]commandParameters)
{
SqlCommandcmd=newSqlCommand();
PrepareCommand(cmdconnectionnullcmdTypecmdTextcommandParameters);
objectval=cmdExecuteScalar();
cmdParametersClear();
returnval;
}
/**////<summary>
///缓存参数数组
///</summary>
///<paramname=cacheKey>参数缓存的键值</param>
///<paramname=cmdParms>被缓存的参数列表</param>
publicstaticvoidCacheParameters(stringcacheKeyparamsSqlParameter[]commandParameters)
{
//编号
parmCache[cacheKey]=commandParameters;
}
/**////<summary>
///获取被缓存的参数
///</summary>
///<paramname=cacheKey>用于查找参数的KEY值</param>
///<returns>返回缓存的参数数组</returns>
publicstaticSqlParameter[]GetCachedParameters(stringcacheKey)
{
SqlParameter[]cachedParms=(SqlParameter[])parmCache[cacheKey];
if(cachedParms==null)
returnnull;
//新建一个参数的克隆列表
SqlParameter[]clonedParms=newSqlParameter[cachedParmsLength];
//通过循环为克隆参数列表赋值
for(inti=j=cachedParmsLength;i<j;i++)
//使用clone方法复制参数列表中的参数
//编号
clonedParms[i]=(SqlParameter)((ICloneable)cachedParms[i])Clone();
returnclonedParms;
}
/**////<summary>
///为执行命令准备参数
///</summary>
///<paramname=cmd>SqlCommand命令</param>
///<paramname=conn>已经存在的数据库连接</param>
///<paramname=trans>数据库事物处理</param>
///<paramname=cmdType>SqlCommand命令类型(存储过程TSQL语句等等)</param>
///<paramname=cmdText>CommandtextTSQL语句例如Select*from
///Products</param>
///<paramname=cmdParms>返回带参数的命令</param>
//编号
privatestaticvoidPrepareCommand(SqlCommandcmdSqlConnectionconnSqlTransactiontransCommandTypecmdTypestringcmdTextSqlParameter[]
cmdParms)
{
//判断数据库连接状态
if(connState!=ConnectionStateOpen)
connOpen();
cmdConnection=conn;
cmdCommandText=cmdText;
//判断是否需要事物处理
if(trans!=null)
cmdTransaction=trans;
cmdCommandType=cmdType;
if(cmdParms!=null)
{
foreach(SqlParameterparmincmdParms)
cmdParametersAdd(parm);
}
}
}
代码是一个比较完整的数据访问组件下面分析这些代码的具体实现
()Using关键字见代码编号Using处理对命名空间的引用通常如果系统提示找不到某个类一定要仔细检查是否引用了这个类的命名空间在C# 中Using还可以实现命名空间的别名例如Using sc =SystemCollections别名就是用来简化命名空间的别名的使用语句是sc::ArrayList list=new sc::Arraylist( )
()注释见代码编号在方法上面一行如果输入///系统会自动将此方法的注释架构搭建好主要包括Summary和param name如果方法有返回值还包括returns如果需要特殊说明可以使用remarks标志根据这个结构可以很容易地描述清楚整个方法的组成及使用方法在注释中使用///将来在代码调用时会出现提示提示的内容就是所添加的注释
()CommandType的使用见代码编号SQL Server数据处理的两种方法存储过程和TSQL语句每条执行语句都有个参数CommandType这是个枚举类型有个选项StoredProcedureTableDirect和Text它们分别表示存储过程表和TSQL语句如果CommandType参数选择StoredProcedure则cmdText参数就是存储过程的名字如果CommandType是Text则cmdText是SQL语句如果CommandType是TableDirect则cmdText是表名称
()Using语句见代码编号在Using语句中用{}定义一个范围在语句完成时释放语句内使用的资源Using语句通常用在获取数据的方法中语句的范围是从打开数据库连接开始到所有使用连接的资源都运行完毕后终止Using语句可以与多个对象一起使用使用Using语句的对象必须继承IDispose接口此接口实现了Dispose方法该方法才是释放对象资源的执行者
()参数数组见代码编号在C#中不允许使用可选参数所以参数通常由不指定大小的数组来实现数组中参数的添加由PrepareCommand方法完成
()SQL事务处理见代码编号事务是指一组相关联的操作在事务处理时通常锁住相关的表等事务处理完成后才解锁这样保证了数据的完整性事务一般包括个方法开始事务执行事务和事务回滚(RollBack)如果事务中的一条语句出现问题则事务回滚其他语句的执行也被取消
()throw见代码编号再次引发捕获的异常目的是向文本中添加异常处理信息如果要引发异常throw和catch一定要搭配使用如果catch有参数则throw也要带参数相反亦然
()哈希表见代码编号表示键/值(key/value)对的组合通过键值的映射来访问哈希代码NET中的哈希表是SystemCollections命名空间提供的一个容器英文名称为HashTable通过key来实现快速查找key区分大小写value存储key对应的值通常表现为object类型当取值时要进行相应的类型转换
()哈希表的同步包装见代码编号private static Hashtable parmCache = Hashtable Synchronized(new Hashtable( ))这条语句实现了哈希表的同步包装包装是基于线程安全的此处的哈希表是static类型的静态变量既然是static就是一次定义全局使用所有的参数都使用这个哈希表那如何保证其他人在修改的时候不影响自己的读取呢?以前可以使用lock的方法先锁定表不允许他人修改读取完毕后再解锁现在NET提供了HashTable的Synchronized方法实现同样的功能不需要手动加锁直接由系统框架完成
()缓存参数列表见代码编号缓存参数列表就是将参数信息保存在已经定义的静态HashTable中因为HashTable是静态的一旦定义就分配了内存地址在项目中随时都可以使用起到了缓存数据的作用
()clone克隆见代码编号在NET中几乎所有继承Collections类的集合都具有clone的方法在获取缓存参数的方法中有下面这句代码clonedParms[i] = (SqlParameter) ((ICloneable)cachedParms[i])Clone( )因为所有的参数都保存在一个HashTable中表中保存的只是参数的名字而参数的内容则是由不同的调用给予不同的值为了正确反映调用者的值必须克隆出一个参数列表由调用者根据功能赋予对应的值
()方法重载见代码编号定义了两个或多个具有相同名称但参数不同的方法在SqlHelper中ExcuteNonQuery被重载了次通过代码中的注释可以很清楚地看出参数列表的不同在实际应用中根据功能环境调用相应的方法
()ConfigurationManager见代码编号是ASPNET 中新加的一个类主要对nfig文件进行管理可以轻松获取在nfig文件中定义的配置通常用来获取数据库连接字符串和个性化配置信息本例在nfig中添加了下面这行数据库连接字符串配置
<connectionStrings >
<add name=connstring connectionString =server=;database=membercard; uid=sa; pwd=/>
</connectionStrings>
()ExcuteNonQuery方法的返回值见代码编号在SqlCommand的方法中ExcuteNonQuery用来执行插入更新或删除等操作程序并不要求有任何返回值但在SqlHelper中定义此方法时返回了一个数值型数据该数据用来表示执行当前语句后数据库中被影响的行数虽然在此定义了返回值但在程序的调用中可以不用返回值直接执行方法例如SqlHelper ExcuteNonQuery( )就是正确的不一定非要写成 int val= SqlHelper ExcuteNonQuery( )如果程序中需要的不是int值还可以进行转换