Pet Shop 游记之DBUtility 一 (SqlHelper中的cmd.Parameters.Clear())

本文解析了PetShop.DBUtility.SqlHelper类中的ExecuteNonQuery方法,阐述了cmd.Parameters.Clear()的作用,避免因SqlParameterCollection重复引用同一SqlParameter对象导致的异常。

今天是进入Pet Shop的第一天,第一站名称PetShop.DBUtility.SqlHelper的类,说实话,这是一个很普通的类,除了cmd.Parameter.Clear()之外。先来看看PetShop.DBUtility.SqlHelper中的两个方法吧:

 

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

{

    SqlCommand cmd = new SqlCommand();

    using (SqlConnection conn = new SqlConnection(connectionString))

    {
        PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
        int val = cmd.ExecuteNonQuery();
        cmd.Parameters.Clear();
        return val;
    }
}

 

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

 

  乍看之下cmd.Parameters.Clear() 语句似乎有此多于,因为执行完cmd.Parameters.Clear()语句后就是return语句了,这意味着cmd将成为垃圾回收器的回收对象,如果说是想及时释放资源的话那似乎不通,这个并不占用资源的对象都需要手动清理那要“托管”何用?于是到论坛上发贴请教。得到的答案很失望,有的说是编程习惯,有的解释Clear()是清零。于是Buidu一下,也有人问同样的问题,但结果一样令人失望。看来只能自己解决了,当我看到cmd.Parameters.Add(parm) 时发现cmd.Parameters是SqlParameterColeection类型的,而SqlParameterColeection在framework中有个怪脾气,“它不用别人用过的”,说得明白点就是:如果一个对象A被一个SqlParameterColeection引用后,此时有另一个SqlParameterColeection再引用A对象时就会发生异常(注意,SqlParameterColeection允许其它类型引用自己引用的对象,比如SqlParameter引用它所引用的对象也不会有问题,只要不是SqlParameterColeection就行)。这样就明天了。我们先删除cmd.Parameters.Clear()语句,然后下面的方面调用ExecuteNonQuery():

 

string conn = "...";//连接字符串

string sqlInsert = "INSERT INTO Cart ( Name,) VALUES ( @Name);";

string sqlSelect = "SELECT * FROM Cart WHERE UniqueID=@UniqueID;";

 

SqlParameter parms = new SqlParameter("@Name", "testUser");

 

ExecuteNonQuery(conn, CommandType.Text, sqlInsert, parms);

ExecuteNonQuery(conn, CommandType.Text, sqlSelect, parms);

 

大家知道每次调用ExecuteNonQuery方法时它都会调用PrepareCommand方法,而PrepareCommand方法执行如下语句:

 

cmd.Parameters.Add(parm);//添加parm的引用到类型为SqlParameterCollection的Parameters对象中

当第一次调用ExecuteNonQuery时会有一个SqlParameterCollection引用parms,注意,这时第一次ExecuteNonQuery调用时产生的cmd还未被垃圾回收器回收,它依然引用着parms,直到真正被回收后,当第二次调用ExecuteNonQuery又会有另一个SqlParameterCollection(cmd.Parameters)将去引用parms,这样就会抛出异常了!!!

 

当添加cmd.Parameters.Clear()后,再调用ExecuteNonQuery即将结果时引用parms的cmd.Parameters就解除了对parms的引用,引用?对!cmd.Parameters.Clear()语句确切的说是解除它对其它对象的引用,而不是清除它包含的对象,cmd.Parameters.Clear()解除对象引用后,它之前引用的对象还是存在的。所以无论ExecuteNonQuery被多次执行都不会有异常。当然,如果不加cmd.Parameters.Clear()语句也可以,那么上面的代码应该这样写:

 

ExecuteNonQuery(conn, CommandType.Text, sqlInsert, new SqlParameter("@Name", "testUser"));

ExecuteNonQuery(conn, CommandType.Text, sqlSelect, new SqlParameter("@Name", "testUser"));

 

浅见至此结束!希望对一些程序员有望,如用有不正确的地方谢谢您的指点!

using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Data.SqlClient; using System.Collections; using System.Configuration; namespace DBUtility { public class DbHelperSQL { // Fields public static string connectionString; // Methods static DbHelperSQL() { connectionString = ConfigurationManager.AppSettings["ConnectionString"]; } public DbHelperSQL() { } private static SqlCommand BuildIntCommand(SqlConnection connection, string storedProcName, IDataParameter[] parameters) { SqlCommand command = BuildQueryCommand(connection, storedProcName, parameters); command.Parameters.Add(new SqlParameter("ReturnValue", SqlDbType.Int, 4, ParameterDirection.ReturnValue, false, 0, 0, string.Empty, DataRowVersion.Default, null)); return command; } private static SqlCommand BuildQueryCommand(SqlConnection connection, string storedProcName, IDataParameter[] parameters) { SqlCommand command = new SqlCommand(storedProcName, connection); command.CommandType = CommandType.StoredProcedure; foreach (SqlParameter parameter in parameters) { if (parameter != null) { if (((parameter.Direction == ParameterDirection.InputOutput) || (parameter.Direction == ParameterDirection.Input)) && (parameter.Value == null)) { parameter.Value = DBNull.Value; } command.Parameters.Add(parameter); } } return command; } public static SqlDataReader ExecuteReader(string strSQL) { SqlDataReader dr; SqlConnection connection = new SqlConnection(connectionString); SqlCommand cmd = new SqlCommand(strSQL, connection); try { connection.Open(); dr= cmd.ExecuteReader(); } catch (SqlException e) { throw new Exception(e.Message); } return dr; } public static SqlDataReader ExecuteReader(string SQLString, params SqlParameter[] cmdParms) { SqlDataReader dr; SqlConnection connection = new SqlConnection(connectionString); SqlCommand cmd = new SqlCommand(); try { PrepareCommand(cmd, connection, null, SQLString, cmdParms); SqlDataReader myReader = cmd.ExecuteReader(); cmd.Parameters.Clear(); dr = myReader; } catch (SqlException e) { throw new Exception(e.Message); } return dr; } public static int ExecuteSql(string SQLString) { int count; using (SqlConnection connection = new SqlConnection(connectionString)) { using (SqlCommand cmd = new SqlCommand(SQLString, connection)) { try { connection.Open(); return cmd.ExecuteNonQuery(); } catch (SqlException E) { connection.Close(); throw new Exception(E.Message); } } } return count; } public static int ExecuteSql(string SQLString, string content) { int count; using (SqlConnection connection = new SqlConnection(connectionString)) { SqlCommand cmd = new SqlCommand(SQLString, connection); SqlParameter myParameter = new SqlParameter("@content", SqlDbType.NText); myParameter.Value = content; cmd.Parameters.Add(myParameter); try { connection.Open(); count = cmd.ExecuteNonQuery(); } catch (SqlException E) { throw new Exception(E.Message); } finally { cmd.Dispose(); connection.Close(); } } return count; } public static int ExecuteSql(string SQLString, params SqlParameter[] cmdParms) { int count; using (SqlConnection connection = new SqlConnection(connectionString)) { using (SqlCommand cmd = new SqlCommand()) { try { PrepareCommand(cmd, connection, null, SQLString, cmdParms); int rows = cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); return rows; } catch (SqlException E) { throw new Exception(E.Message); } } } return count; } public static int ExecuteSqlByTime(string SQLString, int Times) { int count; using (SqlConnection connection = new SqlConnection(connectionString)) { using (SqlCommand cmd = new SqlCommand(SQLString, connection)) { try { connection.Open(); cmd.CommandTimeout = Times; return cmd.ExecuteNonQuery(); } catch (SqlException E) { connection.Close(); throw new Exception(E.Message); } } } return count; } public static object ExecuteSqlGet(string SQLString, string content) { object esg; using (SqlConnection connection = new SqlConnection(connectionString)) { SqlCommand cmd = new SqlCommand(SQLString, connection); SqlParameter myParameter = new SqlParameter("@content", SqlDbType.NText); myParameter.Value = content; cmd.Parameters.Add(myParameter); try { connection.Open(); object obj = cmd.ExecuteScalar(); if (object.Equals(obj, null) || object.Equals(obj, DBNull.Value)) { return null; } esg = obj; } catch (SqlException E) { throw new Exception(E.Message); } finally { cmd.Dispose(); connection.Close(); } } return esg; } public static int ExecuteSqlInsertImg(string strSQL, byte[] fs) { int count; using (SqlConnection connection = new SqlConnection(connectionString)) { SqlCommand cmd = new SqlCommand(strSQL, connection); SqlParameter myParameter = new SqlParameter("@fs", SqlDbType.Image); myParameter.Value = fs; cmd.Parameters.Add(myParameter); try { connection.Open(); count = cmd.ExecuteNonQuery(); } catch (SqlException E) { throw new Exception(E.Message); } finally { cmd.Dispose(); connection.Close(); } } return count; } public static void ExecuteSqlTran(ArrayList SQLStringList) { using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); SqlCommand cmd = new SqlCommand(); cmd.Connection = conn; SqlTransaction tx = conn.BeginTransaction(); cmd.Transaction = tx; try { for (int n = 0; n < SQLStringList.Count; n++) { string strsql = SQLStringList[n].ToString(); if (strsql.Trim().Length > 1) { cmd.CommandText = strsql; cmd.ExecuteNonQuery(); } } tx.Commit(); } catch (SqlException E) { tx.Rollback(); throw new Exception(E.Message); } } } public static void ExecuteSqlTran(Hashtable SQLStringList) { using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); using (SqlTransaction trans = conn.BeginTransaction()) { SqlCommand cmd = new SqlCommand(); try { foreach (DictionaryEntry myDE in SQLStringList) { string cmdText = myDE.Key.ToString(); SqlParameter[] cmdParms = (SqlParameter[])myDE.Value; PrepareCommand(cmd, conn, trans, cmdText, cmdParms); int val = cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); trans.Commit(); } } catch { trans.Rollback(); throw; } } } } public static bool Exists(string strSql) { int cmdresult; object obj = GetSingle(strSql); if (object.Equals(obj, null) || object.Equals(obj, DBNull.Value)) { cmdresult = 0; } else { cmdresult = int.Parse(obj.ToString()); } if (cmdresult == 0) { return false; } return true; } public static bool Exists(string strSql, params SqlParameter[] cmdParms) { int cmdresult; object obj = GetSingle(strSql, cmdParms); if (object.Equals(obj, null) || object.Equals(obj, DBNull.Value)) { cmdresult = 0; } else { cmdresult = int.Parse(obj.ToString()); } if (cmdresult == 0) { return false; } return true; } public static int GetMaxID(string FieldName, string TableName) { object obj = GetSingle("select max(" + FieldName + ")+1 from " + TableName); if (obj == null) { return 1; } return int.Parse(obj.ToString()); } public static object GetSingle(string SQLString) { object gs; using (SqlConnection connection = new SqlConnection(connectionString)) { using (SqlCommand cmd = new SqlCommand(SQLString, connection)) { try { connection.Open(); object obj = cmd.ExecuteScalar(); if (object.Equals(obj, null) || object.Equals(obj, DBNull.Value)) { return null; } return obj; } catch (SqlException e) { connection.Close(); throw new Exception(e.Message); } } } return gs; } public static object GetSingle(string SQLString, params SqlParameter[] cmdParms) { object gs; using (SqlConnection connection = new SqlConnection(connectionString)) { using (SqlCommand cmd = new SqlCommand()) { try { PrepareCommand(cmd, connection, null, SQLString, cmdParms); object obj = cmd.ExecuteScalar(); cmd.Parameters.Clear(); if (object.Equals(obj, null) || object.Equals(obj, DBNull.Value)) { return null; } return obj; } catch (SqlException e) { throw new Exception(e.Message); } } } return gs; } private static void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, 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 = CommandType.Text; if (cmdParms != null) { foreach (SqlParameter parameter in cmdParms) { if (((parameter.Direction == ParameterDirection.InputOutput) || (parameter.Direction == ParameterDirection.Input)) && (parameter.Value == null)) { parameter.Value = DBNull.Value; } cmd.Parameters.Add(parameter); } } } public static DataSet Query(string SQLString) { using (SqlConnection connection = new SqlConnection(connectionString)) { DataSet ds = new DataSet(); try { connection.Open(); new SqlDataAdapter(SQLString, connection).Fill(ds, "ds"); } catch (SqlException ex) { throw new Exception(ex.Message); } return ds; } } public static DataSet Query(string SQLString,int pageindx,int pagesize,string tablename) { using (SqlConnection connection = new SqlConnection(connectionString)) { DataSet ds = new DataSet(); try { connection.Open(); new SqlDataAdapter(SQLString, connection).Fill(ds,pageindx,pagesize,tablename); } catch (SqlException ex) { throw new Exception(ex.Message); } return ds; } } public static DataSet Query(string SQLString, int Times) { using (SqlConnection connection = new SqlConnection(connectionString)) { DataSet ds = new DataSet(); try { connection.Open(); SqlDataAdapter command = new SqlDataAdapter(SQLString, connection); command.SelectCommand.CommandTimeout = Times; command.Fill(ds, "ds"); } catch (SqlException ex) { throw new Exception(ex.Message); } return ds; } } public static DataSet Query(string SQLString, params SqlParameter[] cmdParms) { DataSet dsq; using (SqlConnection connection = new SqlConnection(connectionString)) { SqlCommand cmd = new SqlCommand(); PrepareCommand(cmd, connection, null, SQLString, cmdParms); using (SqlDataAdapter da = new SqlDataAdapter(cmd)) { DataSet ds = new DataSet(); try { da.Fill(ds, "ds"); cmd.Parameters.Clear(); } catch (SqlException ex) { throw new Exception(ex.Message); } dsq = ds; } } return dsq; } public static DataSet Query(string SQLString,string tablename) { using (SqlConnection connection = new SqlConnection(connectionString)) { DataSet ds = new DataSet(); try { connection.Open(); new SqlDataAdapter(SQLString, connection).Fill(ds, tablename); } catch (SqlException ex) { throw new Exception(ex.Message); } return ds; } } public static SqlDataReader RunProcedure(string storedProcName, IDataParameter[] parameters) { SqlConnection connection = new SqlConnection(connectionString); connection.Open(); SqlCommand command = BuildQueryCommand(connection, storedProcName, parameters); command.CommandType = CommandType.StoredProcedure; return command.ExecuteReader(); } public static int RunProcedure(string storedProcName, IDataParameter[] parameters, out int rowsAffected) { using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); SqlCommand command = BuildIntCommand(connection, storedProcName, parameters); rowsAffected = command.ExecuteNonQuery(); int result = (int)command.Parameters["ReturnValue"].Value; connection.Close(); return result; } } public static DataSet RunProcedure(string storedProcName, IDataParameter[] parameters, string tableName) { using (SqlConnection connection = new SqlConnection(connectionString)) { DataSet dataSet = new DataSet(); connection.Open(); SqlDataAdapter sqlDA = new SqlDataAdapter(); sqlDA.SelectCommand = BuildQueryCommand(connection, storedProcName, parameters); sqlDA.Fill(dataSet, tableName); connection.Close(); return dataSet; } } public static DataSet RunProcedure(string storedProcName, IDataParameter[] parameters, string tableName, int Times) { using (SqlConnection connection = new SqlConnection(connectionString)) { DataSet dataSet = new DataSet(); connection.Open(); SqlDataAdapter sqlDA = new SqlDataAdapter(); sqlDA.SelectCommand = BuildQueryCommand(connection, storedProcName, parameters); sqlDA.SelectCommand.CommandTimeout = Times; sqlDA.Fill(dataSet, tableName); connection.Close(); return dataSet; } } public static void RunStatProcedure(string storedProcName, IDataParameter[] parameters, out int rowsAffected) { using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); SqlCommand command = BuildIntCommand(connection, storedProcName, parameters); rowsAffected = command.ExecuteNonQuery(); connection.Close(); } } } }
最新发布
07-25
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值