我有以下代码(这里有伪值以便于阅读),其中第一个连接返回大量数据(数千行)。 SqlDataReader通过reader.Read()
逐个读取它们,然后打开一个新连接以使用新值更新每一行:
using (SqlConnection conn = new SqlConnection(connString))
using (SqlCommand cmd = new SqlCommand("sp1", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@param1", param1);
cmd.Connection.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
try
{
string hash= utils.SHA256.Hashing((string)reader["firstRow"], saltValue);
using (SqlConnection conn2 = new SqlConnection(connString))
using (SqlCommand cmd2 = new SqlCommand("sp2", conn2))
{
cmd2.CommandType = CommandType.StoredProcedure;
cmd2.Parameters.AddWithValue("@param1", param1);
cmd2.Parameters.AddWithValue("@param2", param2);
cmd2.Connection.Open();
cmd2.ExecuteNonQuery();
}
}
catch (SqlException ex)
{
//something
}
}
}
}
但它会引发错误:
[InvalidOperationException: Invalid attempt to call Read when reader is closed.]
System.Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout) +640
System.Data.SqlClient.SqlDataReader.Read() +9
在开发环境中它工作正常,但这里只有几百行。它会立即抛出错误,因此它不会直接看起来像某种超时,但是嘿 - 我不知道......
答案 0 :(得分:5)
不知道为什么会发生这种情况,但在将实时连接迭代到同一个数据库时执行查询真的是个坏主意。请记住,只要使用DataReader迭代记录,连接就会生效。
更糟糕的是,连续数千次打开然后关闭连接。仅这一点就可以使任何数据库瘫痪。
更改逻辑,将所需的值存储在本地变量中(结构无关紧要),然后仅使用一个连接执行所需的所有存储过程。
例如:
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
List<string[]> values = new List<string[]>();
using (SqlCommand cmd = new SqlCommand("sp1", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@param1", param1);
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
try
{
string hash= utils.SHA256.Hashing((string)reader["firstRow"], saltValue);
string anotherValue = (string)reader["secondRow"];
values.Add(new string[] { hash, anotherValue });
}
catch (SqlException ex)
{
//something
}
}
reader.Close();
}
}
if (values.Count > 0)
{
using (SqlCommand cmd2 = new SqlCommand("sp2", conn))
{
cmd2.CommandType = CommandType.StoredProcedure;
cmd2.Parameters.AddWithValue("@param1", null);
cmd2.Parameters.AddWithValue("@param2", null);
values.ForEach(items =>
{
cmd2.Parameters["@param1"].Value = items[0];
cmd2.Parameters["@param2"].Value = items[1];
cmd2.ExecuteNonQuery();
});
}
}
conn.Close();
}
一个连接,一个执行所有存储过程的命令。真的不需要更多。