以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;
}

 

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


 

 

posted @ 2014-03-31 14:09  苏大小飞  阅读(253)  评论(0编辑  收藏  举报