数据访问组件SqlHelper
数据访问组件是一组通用的访问数据库的代码,在所有项目中都可以用,一般不需要修改。本节使用的是Microsoft提供的数据访问助手,其封装很严密,且应用简单。

首先要先添加一个类,并命名为SqlHelper,系统会提示是否将类放在App_Code文件夹中。此时一定要选择“是”,因为放在此文件夹下,系统会自动进行编译,程序员就可以直接使用,无需另外编译了。

SqlHelper的功能
SqlHelper的目的是从数据库获得信息或将信息保存到数据库。本实例的SqlHelper主要功能如下。

(1)执行不返回数据的T-Sql命令。例如修改会员卡信息、添加会员资料等。

(2)返回一个字段的T-Sql命令。例如获取会员卡类型的积分规则。

(3)返回一组数据。例如获取会员资料、获取所有会员卡类型等。

(4)缓存参数列表。在执行一条语句时,可能有多个参数,为了提高速度,将参数缓存。

(5)读取缓存的参数。

下面用图表的方式描述SqlHelper类的功能,如图7-16所示。

图7-16 SqlHelper功能图

代码清单
在SqlHelper类中添加数据库处理,代码如清单7-4所示。

代码清单 SqlHelper代码

//编号1

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Collections;

using System.Data.SqlClient;

//编号2

/// <summary>

/// 数据库的通用访问代码

/// 此类为抽象类,不允许实例化,在应用时直接调用即可

/// </summary>

public abstract class SqlHelper

{

//获取数据库连接字符串,其属于静态变量且只读,项目中所有文档可以直接使用,但不能修改

//编号13

public static readonly string ConnectionStringLocalTransaction =

ConfigurationManager.ConnectionStrings["connstring"].ConnectionString;

// 哈希表用来存储缓存的参数信息,哈希表可以存储任意类型的参数

//编号8

private static Hashtable parmCache = Hashtable.Synchronized(new

Hashtable());//编号9

/// <summary>

///执行一个不需要返回值的SqlCommand命令,通过指定专用的连接字符串。

/// 使用参数数组形式提供参数列表

/// </summary>

/// <remarks>

/// 使用示例:

/// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure,
         /// "PublishOrders", new SqlParameter("@prodid", 24));

/// </remarks>

/// <param name="connectionString">一个有效的数据库连接字符串</param>

/// <param name="commandType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)

/// </param>

/// <param name="commandText">存储过程的名字或者 T-SQL 语句</param>

/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表

/// </param>

/// <returns>返回一个数值表示此SqlCommand命令执行后影响的行数</returns>

//编号3

public static int ExecuteNonQuery(string connectionString, CommandType cmdType,

string cmdText, params SqlParameter[] commandParameters)

{

SqlCommand cmd = new SqlCommand();

//编号4

using (SqlConnection conn = new SqlConnection(connectionString))

{

//通过PrePareCommand方法将参数逐个加入到SqlCommand的参数集合中

PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);

int val = cmd.ExecuteNonQuery();

//清空SqlCommand中的参数列表

cmd.Parameters.Clear();

//编号14

return val;

}

}

/// <summary>

///执行一条不返回结果的SqlCommand,通过一个已经存在的数据库连接

/// 使用参数数组提供参数

/// </summary>

/// <remarks>

/// 使用示例:

/// int result = ExecuteNonQuery(conn, CommandType.StoredProcedure,

/// "PublishOrders", new SqlParameter("@prodid", 24));

/// </remarks>

/// <param name="conn">一个现有的数据库连接</param>

/// <param name="commandType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)

/// </param>

/// <param name="commandText">存储过程的名字或者 T-SQL 语句</param>

/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表

/// </param>

/// <returns>返回一个数值表示此SqlCommand命令执行后影响的行数</returns>

//编号5

public static int ExecuteNonQuery(SqlConnection connection, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)

{

SqlCommand cmd = new SqlCommand();

PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);

int val = cmd.ExecuteNonQuery();

cmd.Parameters.Clear();

return val;

}

/// <summary>

/// 执行一条不返回结果的SqlCommand,通过一个已经存在的数据库事物处理

/// 使用参数数组提供参数

/// </summary>

/// <remarks>

/// 使用示例:

/// int result = ExecuteNonQuery(trans, CommandType.StoredProcedure,

/// "PublishOrders", new SqlParameter("@prodid", 24));

/// </remarks>

/// <param name="trans">一个存在的 sql 事物处理</param>

/// <param name="commandType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)

/// </param>

/// <param name="commandText">存储过程的名字或者 T-SQL 语句</param>

/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表

/// </param>

/// <returns>返回一个数值表示此SqlCommand命令执行后影响的行数</returns>

//编号12

public static int ExecuteNonQuery(SqlTransaction trans, CommandType cmdType,

string cmdText, params SqlParameter[] commandParameters)

{

SqlCommand cmd = new SqlCommand();

PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, commandParameters);

int val = cmd.ExecuteNonQuery();

cmd.Parameters.Clear();

return val;

}

/// <summary>

/// 执行一条返回结果集的SqlCommand命令,通过专用的连接字符串。

/// 使用参数数组提供参数

/// </summary>

/// <remarks>

/// 使用示例:

/// SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure,

/// "PublishOrders", new SqlParameter("@prodid", 24));

/// </remarks>

/// <param name="connectionString">一个有效的数据库连接字符串</param>

/// <param name="commandType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)

/// </param>

/// <param name="commandText">存储过程的名字或者 T-SQL 语句</param>

/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表

/// </param>

/// <returns>返回一个包含结果的SqlDataReader</returns>

public static SqlDataReader ExecuteReader(string connectionString, CommandType

cmdType, string cmdText, params SqlParameter[] commandParameters)

{

SqlCommand cmd = new SqlCommand();

SqlConnection conn = new SqlConnection(connectionString);

// 在这里使用try/catch处理是因为如果方法出现异常,则SqlDataReader就不存在,

//CommandBehavior.CloseConnection的语句就不会执行,触发的异常由catch捕获。

//关闭数据库连接,并通过throw再次引发捕捉到的异常。

try

{

PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);

SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

cmd.Parameters.Clear();

return rdr;

}

catch

{

conn.Close();

throw; //编号7

}

}

/// <summary>

/// 执行一条返回第一条记录第一列的SqlCommand命令,通过专用的连接字符串。

/// 使用参数数组提供参数

/// </summary>

/// <remarks>

/// 使用示例:

/// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure,

/// "PublishOrders", new SqlParameter("@prodid", 24));

/// </remarks>

/// <param name="connectionString">一个有效的数据库连接字符串</param>

/// <param name="commandType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)

/// </param>

/// <param name="commandText">存储过程的名字或者 T-SQL 语句</param>

/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表

/// </param>

/// <returns>返回一个object类型的数据,可以通过 Convert.To{Type}方法转换类型</returns>

public static object ExecuteScalar(string connectionString, CommandType

cmdType, string cmdText, params SqlParameter[] commandParameters)

{

SqlCommand cmd = new SqlCommand();

using (SqlConnection connection = new SqlConnection(connectionString))

{

PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);

object val = cmd.ExecuteScalar();

cmd.Parameters.Clear();

return val;

}

}

/// <summary>

/// 执行一条返回第一条记录第一列的SqlCommand命令,通过已经存在的数据库连接。

/// 使用参数数组提供参数

/// </summary>

/// <remarks>

/// 使用示例:

/// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure,

/// "PublishOrders", new SqlParameter("@prodid", 24));

/// </remarks>

/// <param name="conn">一个已经存在的数据库连接</param>

/// <param name="commandType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)

/// </param>

/// <param name="commandText">存储过程的名字或者 T-SQL 语句</param>

/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表

/// </param>

/// <returns>返回一个object类型的数据,可以通过 Convert.To{Type}方法转换类型

/// </returns>

public static object ExecuteScalar(SqlConnection connection, CommandType

cmdType, string cmdText, params SqlParameter[] commandParameters)

{

SqlCommand cmd = new SqlCommand();

PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);

object val = cmd.ExecuteScalar();

cmd.Parameters.Clear();

return val;

}

/// <summary>

/// 缓存参数数组

/// </summary>

/// <param name="cacheKey">参数缓存的键值</param>

/// <param name="cmdParms">被缓存的参数列表</param>

public static void CacheParameters(string cacheKey, params SqlParameter[]

commandParameters)

{

//编号10

parmCache[cacheKey] = commandParameters;

}

/// <summary>

/// 获取被缓存的参数

/// </summary>

/// <param name="cacheKey">用于查找参数的KEY值</param>

/// <returns>返回缓存的参数数组</returns>

public static SqlParameter[] GetCachedParameters(string cacheKey)

{

SqlParameter[] cachedParms = (SqlParameter[])parmCache[cacheKey];

if (cachedParms == null)

return null;

//新建一个参数的克隆列表

SqlParameter[] clonedParms = new SqlParameter[cachedParms.Length];

//通过循环为克隆参数列表赋值

for (int i = 0, j = cachedParms.Length; i < j; i++)

//使用clone方法复制参数列表中的参数

//编号11

clonedParms[i] = (SqlParameter)((ICloneable)cachedParms[i]).Clone();

return clonedParms;

}

/// <summary>

/// 为执行命令准备参数

/// </summary>

/// <param name="cmd">SqlCommand 命令</param>

/// <param name="conn">已经存在的数据库连接</param>

/// <param name="trans">数据库事物处理</param>

/// <param name="cmdType">SqlCommand命令类型 (存储过程,T-SQL语句,等等。) </param>

/// <param name="cmdText">Command text,T-SQL语句 例如 Select * from

/// Products</param>

/// <param name="cmdParms">返回带参数的命令</param>

//编号6

private static void PrepareCommand(SqlCommand cmd, SqlConnection conn,

SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[]
         cmdParms)

{

//判断数据库连接状态

if (conn.State != ConnectionState.Open)

conn.Open();

cmd.Connection = conn;

cmd.CommandText = cmdText;

//判断是否需要事物处理

if (trans != null)

cmd.Transaction = trans;

cmd.CommandType = cmdType;

if (cmdParms != null)

{

foreach (SqlParameter parm in cmdParms)

cmd.Parameters.Add(parm);

}

}

}

代码技术分析
代码清单7-4是一个比较完整的数据访问组件,下面分析这些代码的具体实现。

(1)Using关键字:见代码编号1。Using处理对命名空间的引用。通常,如果系统提示找不到某个类,一定要仔细检查是否引用了这个类的命名空间。在C# 2.0中Using还可以实现命名空间的别名,例如:Using sc =System.Collections。别名就是用来简化命名空间的,别名的使用语句是:sc::ArrayList list=new sc::Arraylist( )。

(2)注释:见代码编号2。在方法上面一行如果输入“///”,系统会自动将此方法的注释架构搭建好,主要包括Summary和param name。如果方法有返回值,还包括returns;如果需要特殊说明可以使用remarks标志。根据这个结构,可以很容易地描述清楚整个方法的组成及使用方法。在注释中使用“///”,将来在代码调用时,会出现提示,提示的内容就是所添加的注释。

(3)CommandType的使用:见代码编号3。SQL Server数据处理的两种方法:存储过程和T-SQL语句。每条执行语句都有个参数CommandType,这是个枚举类型,有3个选项:StoredProcedure、TableDirect和Text。它们分别表示存储过程、表和T-SQL语句。如果CommandType参数选择StoredProcedure,则cmdText参数就是存储过程的名字;如果CommandType是Text,则cmdText是SQL语句;如果CommandType是TableDirect,则cmdText是表名称。

(4)Using语句:见代码编号4。在Using语句中,用“{}”定义一个范围,在语句完成时释放语句内使用的资源。Using语句通常用在获取数据的方法中,语句的范围是从打开数据库连接开始,到所有使用连接的资源都运行完毕后终止。Using语句可以与多个对象一起使用。使用Using语句的对象必须继承IDispose接口。此接口实现了Dispose方法,该方法才是释放对象资源的执行者。

(5)参数数组:见代码编号5。在C#中不允许使用可选参数,所以参数通常由不指定大小的数组来实现。数组中参数的添加由PrepareCommand方法完成。

(6)SQL事务处理:见代码编号6。事务是指一组相关联的操作。在事务处理时,通常锁住相关的表,等事务处理完成后才解锁,这样保证了数据的完整性。事务一般包括3个方法:开始事务、执行事务和事务回滚(RollBack)。如果事务中的一条语句出现问题,则事务回滚,其他语句的执行也被取消。

(7)throw:见代码编号7。再次引发捕获的异常,目的是向文本中添加异常处理信息。如果要引发异常,throw和catch一定要搭配使用,如果catch有参数,则throw也要带参数,相反亦然。

(8)哈希表:见代码编号8。表示键/值(key/value)对的组合。通过键值的映射来访问哈希代码。.NET中的哈希表是System.Collections命名空间提供的一个容器,英文名称为HashTable,通过key来实现快速查找,key区分大小写。value存储key对应的值,通常表现为object类型,当取值时要进行相应的类型转换。

(9)哈希表的同步包装:见代码编号9。private static Hashtable parmCache = Hashtable. Synchronized(new Hashtable( ))这条语句实现了哈希表的同步包装,包装是基于线程安全的。此处的哈希表是static类型的静态变量,既然是static,就是一次定义,全局使用。所有的参数都使用这个哈希表,那如何保证其他人在修改的时候不影响自己的读取呢?以前可以使用lock的方法先锁定表,不允许他人修改,读取完毕后再解锁。现在.NET提供了HashTable的Synchronized方法,实现同样的功能,不需要手动加锁,直接由系统框架完成。

(10)缓存参数列表:见代码编号10。缓存参数列表就是将参数信息保存在已经定义的静态HashTable中。因为HashTable是静态的,一旦定义,就分配了内存地址,在项目中随时都可以使用,起到了缓存数据的作用。

(11)clone:克隆。见代码编号11。在.NET中,几乎所有继承Collections类的集合都具有clone的方法。在获取缓存参数的方法中有下面这句代码:clonedParms[i] = (SqlParameter) ((ICloneable)cachedParms[i]).Clone( )。因为所有的参数都保存在一个HashTable中,表中保存的只是参数的名字,而参数的内容则是由不同的调用给予不同的值。为了正确反映调用者的值,必须克隆出一个参数列表,由调用者根据功能赋予对应的值。

(12)方法重载:见代码编号12。定义了两个或多个具有相同名称但参数不同的方法。在SqlHelper中,ExcuteNonQuery被重载了4次,通过代码中的注释可以很清楚地看出参数列表的不同。在实际应用中,根据功能环境调用相应的方法。

(13)ConfigurationManager:见代码编号13。是ASP.NET 2.0中新加的一个类,主要对Web.config文件进行管理。可以轻松获取在Web.config文件中定义的配置,通常用来获取数据库连接字符串和个性化配置信息。本例在Web.config中添加了下面这行数据库连接字符串配置。

<connectionStrings >

<add name="connstring" connectionString ="server=.;database=membercard; uid=sa; pwd="/>

</connectionStrings>

(14)ExcuteNonQuery方法的返回值:见代码编号14。在SqlCommand的方法中,ExcuteNonQuery用来执行插入、更新或删除等操作。程序并不要求有任何返回值,但在SqlHelper中定义此方法时返回了一个数值型数据。该数据用来表示执行当前语句后数据库中被影响的行数。虽然在此定义了返回值,但在程序的调用中,可以不用返回值,直接执行方法。例如:SqlHelper. ExcuteNonQuery( )就是正确的,不一定非要写成 int val= SqlHelper. ExcuteNonQuery( )。如果程序中需要的不是int值,还可以进行转换。
---------------------
作者:风雨潇潇
来源:CSDN
原文:https://blog.csdn.net/Long_carol/article/details/6550327
版权声明:本文为博主原创文章,转载请附上博文链接!

微软 SqlHelper代码、功能、用法介绍:高效的组件的更多相关文章

  1. XMLHttpRequest用法介绍

    前言: 传统的Web应用请求服务器返回的一般是是完整的HTML页面,这样往往就需要页面进行刷新操作,不仅耗时而且用户体验度也不好.最典型的代表就是form表单登录操作了.如果登录失败往往是跳转到原网页 ...

  2. STL vector用法介绍

    STL vector用法介绍 介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和f ...

  3. block(代码块)的介绍以及使用方法和变量之间的关系

    http://blog.csdn.net/menxu_work/article/details/8762848 block(代码块)的介绍以及使用方法和变量之间的关系 block(代码块)的介绍以及使 ...

  4. SVN组成中trunk,branches and tags功能用法详解

    SVN组成中trunk,branches and tags功能用法详解  我相信初学开发在SVN作为版本管理时,都估计没可能考虑到如何灵活的运用SVN来管理开发代码的版本,下面我就摘录一篇文章来简单说 ...

  5. LinqToXml高级用法介绍

    LinqToXml高级用法介绍 一.函数构造 什么是函数构造?其是指通过单个语句构建XML树的能力. 那么它有什么作用呢? 作用1.用单个表达式快速创建复杂的XML树 见实例代码CreateXml( ...

  6. TensorFlow tf.app&tf.app.flags用法介绍

    TensorFlow tf.app&tf.app.flags用法介绍 TensorFlow tf.app argparse  tf.app.flags 下面介绍 tf.app.flags.FL ...

  7. pm2常用的命令用法介绍

    pm2 是一个带有负载均衡功能的Node应用的进程管理器.当你要把你的独立代码利用全部的服务器上的所有CPU,并保证进程永远都活着,0秒的重载, PM2是完美的,下面我们来看pm2常用的命令用法介绍吧 ...

  8. richface的配置、用法介绍和注意事项

    richface的配置.用法介绍和注意事项一.RichFaces (3.1.x) 技术需求 1.JDK 1.5 或更高版本: 2.支持的 JSF 实现: Sun JSF 1.1 RI - 1.2 My ...

  9. MyEclipse相关用法介绍

    MyEclipse相关用法介绍 ================================================================================ 编辑: ...

随机推荐

  1. 国内Git官网下载windows版本慢的问题,推荐一个国内镜像

    话不多说了,给你们镜像地址: https://npm.taobao.org/mirrors/git-for-windows/ 不用谢.点右边打赏个一毛钱,告诉我你来过        !_!

  2. 用CUDA写出比Numpy更快的规约求和函数

    技术背景 在前面的几篇博客中我们介绍了在Python中使用Numba来写CUDA程序的一些基本操作和方法,并且展示了GPU加速的实际效果.在可并行化的算法中,比如计算两个矢量的加和,或者是在分子动力学 ...

  3. IMO 2021 第一题题解及相关拓展问题分析

    IMO 2021 第 1 题: 设整数 n ≥ 100.伊凡把 n, n + 1, ..., 2n 的每个数写在不同的卡片上.然后他将这 n + 1 张卡片打乱顺序并分成两堆.证明:至少有一堆中包含两 ...

  4. 基于Nginx实现负载均衡的部署

    Nginx(enginex)是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器. nginx官方网站:http://nginx.org/ nginx plus收费软件, ...

  5. Django项目使用requirements.txt文件

    1.生成requirements.txt pip freeze > requirements.txt 2.使用requirements.txt pip install -r requiremen ...

  6. Docker(36)- docker run 的流程和原理

    背景 目前项目组上, Docker 用的非常重,所有微服务都是通过 docker 来部署的 所以不能仅仅会命令,还得会一些原理的东西,特此补一篇基础点的,后面再更加深入一些 docker 原理 本篇学 ...

  7. Spring AOP Aspect的简单实现(基于XML)

    第一步:导包 第二步:实现类和切面类 Service("userService")public class IUserviceImpl implements IUserServic ...

  8. SQL-Instead of 触发器

    定义及优点 INSTEAD OF触发器指定执行触发器而不是执行触发 的SQL 语句,从而替代触发语句的操作.        在表或视图上,每个 INSERT.UPDATE 或 DELETE 语句最多可 ...

  9. Fastjson 1.2.22-24 反序列化漏洞分析(1)

    Fastjson 1.2.22-24 反序列化漏洞分析(1) 前言 FastJson是alibaba的一款开源JSON解析库,可用于将Java对象转换为其JSON表示形式,也可以用于将JSON字符串转 ...

  10. go build 与go install

    相同点都能生成可执行文件 不同点go build 不能生成包文件, go install 可以生成包文件go build 生成可执行文件在当前目录下, go install 生成可执行文件在bin目录 ...