一般情況下,我們定義的一個SqlParameter參數數組,如:
SqlParameter[] parms =
{
new SqlParameter("@DateTime1", dtBegin),
new SqlParameter("@DateTime2", dtEnd)
};
如果只給一個SqlCommand使用,這種情況的參數使用,不會出現異常,但如果該參數數組同時給兩個Sqlcommand使用,就會出現如下異常:
System.ArgumentException: 另一個SqlParameterCollection中已包含SqlParameter。
原因如下:聲明的SqlParameter數組,而在循環的內部,每一次執行ExecuteNonQuery(或者其它命令方法)都由該方法內部的IDbCommand.Parameters.Add(IDbDataParameter)將SqlParameter數組添加到IDbCommand的IDataParameterCollection中。而framework機制限制兩個IDataParameterCollection指向同一個對象。雖然ExecuteNonQuery方法內部聲明了一個IDbCommand的臨時對象,理論上講,這個包含了IDataParameterCollection的IDbCommand對象會在ExecuteNonQuery方法結束時從內存中釋放。但是實際上可能是由於垃圾回收機制並沒有將IDbCommand臨時對象即時的回收,而且改對象綁定的Parameter集合也存在,就像一個DropDownList添加Item一樣。這樣在下一個循環執行的時候,會導致兩個IDataParameterCollection指向同一個對象,此時出現問題。
解決方案一:在每一次循環時,重新生成對象,但這樣會產生大量的垃圾變量,不可取。
解決方案二:將使用完之后的Command命令的Parameters集合清空。推薦使用,類似代碼如下:
/// <summary>
/// 獲取一個DataTable
/// </summary>
public static DataTable GetDataTable(
string connDBStr, string sql, params SqlParameter[] cmdParms)
{
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn = new SqlConnection(connDBStr))
{
PrepareSqlCommand(cmd, conn, null, sql, cmdParms);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable (SetSqlAsDataTableName(sql));
da.Fill(dt);
cmd.Parameters.Clear();//多了這一句,就解決了問題
return dt;
}
}
另外,如果不是數組,只是一個SqlParameter變量,如:
SqlParameter parm =
new SqlParameter("@Cust_Id", CustId.Trim());;
則多次被SqlCommand使用,不會出現問題,我已經做了試驗!