以SqlHelper为例论面向对象中封装的使用

引言:  



  在使用面向对象方法编写的程序中,会有一些工具类,如Utility,xxHelper等。



  比如1)操作数据库的过程,一般步骤都是:1.准备数据库地址、表名等信息;2.建立连接;3.准备要执行sql语句或存储过程;4.设置执行参数;5.执行sql语句;6.读取执行结果;7.处理异常、关闭连接、释放资源。



  再比如2)联网获取/发送数据的过程,一般步骤都是:1.准备Url,设置连接方式及参数;2.建立连接;3.发送请求;4.读取请求结果;5.处理异常、关闭连接、释放资源。



  对比以上两个操作我们发现:对于建立连接发送请求的这种操作,有很大一部分的工作时前期准备工作和善后工作,且这些工作在每次请求时基本相同。

  

  本文将以SqlHelper对ADO.NET的封装为例,探讨一下面向对象中封装的使用。

  下面展示一小段使用ADO.NET(一组向 .NET Framework 程序员公开数据访问服务的类)操作数据库的代码:

private void button1_Click(object sender, EventArgs e) { //前期准备工作

    string connetionString = null; SqlConnection cnn ; SqlCommand cmd ; string sql = null; connetionString = "Data Source=ServerName;Initial Catalog=DatabaseName;User ID=UserName;Password=Password"; sql = "Your SQL Statemnt Here"; cnn = new SqlConnection(connetionString); try { cnn.Open(); cmd = new SqlCommand(sql, cnn); //执行

 cmd.ExecuteNonQuery(); //善后工作

 cmd.Dispose(); cnn.Close(); MessageBox.Show (" ExecuteNonQuery in SqlCommand executed !!"); } catch (Exception ex) { MessageBox.Show("Can not open connection ! "); } }

  可以看到大量的前期准备工作和善后工作的代码(我称之为“边缘代码”),而真正执行请求的代码只有一句话。在一个应用中,我们需要操作数据库的地方可能不下数十次,如果每一次操作数据库都复制粘贴一遍这些“边缘代码”,那样不仅代码写起来累人,看着也很低端。而且如果有一天需要改变连接数据库的设置时,几十处内容都需要重新复制粘贴一遍,不管你能不能受了,我是受不了。

  所以便有了“封装”这一举动,把这些细节封装到一个类中(不妨叫SqlHelper),操作数据库时我们希望这些“边缘代码”自动执行。下面代码便是一个简单封装的结果:

//使用SqlHelper封装后

public static void Insert(ServiceCall serviceCall) { List<SqlParameter> paraList = new List<SqlParameter>(); paraList.Add(new SqlParameter("@url",serviceCall.Url)); paraList.Add(new SqlParameter("@payload",serviceCall.Payload)); SqlHelper.ExecuteNonQuery(Configuration.ConnectionString, CommandType.StoredProcedure, "InsertServiceCallLog", paraList.ToArray()); }

  封装后的代码清爽了许多!我们只传了必要的3个参数(数据库地址,sql语句,参数)给工具类(SqlHelper),其余的建立连接,设置参数,释放资源等都在工具类(SqlHelper)中悄悄的做了,是不是很爽?!


  这只是一次简单的尝试,看这个封装类是怎么实现的:

//内部实现

public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters) { //create & open a SqlConnection, and dispose of it after we are done.

    using (SqlConnection cn = new SqlConnection(connectionString)) { cn.Open(); //call the overload that takes a connection in place of the connection string

        return ExecuteNonQuery(cn, commandType, commandText, commandParameters); } } public static int ExecuteNonQuery(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters) { //create a command and prepare it for execution

    SqlCommand cmd = new SqlCommand(); PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters); //finally, execute the command.

    int retval = cmd.ExecuteNonQuery(); // detach the SqlParameters from the command object, so they can be used again.

 cmd.Parameters.Clear(); return retval; }

  

  依然是建立连接,打开链接,设置参数,执行语句,善后处理这个过程。

private static void PrepareCommand(SqlCommand command, SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters) { //if the provided connection is not open, we will open it

    if (connection.State != ConnectionState.Open) { connection.Open(); } //associate the connection with the command

    command.Connection = connection; //set the command text (stored procedure name or SQL statement)

    command.CommandText = commandText; //if we were provided a transaction, assign it.

    if (transaction != null) { command.Transaction = transaction; } //set the command type

    command.CommandType = commandType; //attach the command parameters if they are provided

    if (commandParameters != null) { AttachParameters(command, commandParameters); } return; }

 

  这样封装处理之后,每次再操作起数据库来就方便许多了。这就是面向对象中封装的使用,这种思想通过示例代码来阐述因该比较容易理解了吧。


 

 

你可能感兴趣的:(面向对象)