在项目中,我调用一个方法来使用 SqlConnection块查询附加信息,但后来我使用另一个 sqlconnection块验证是否存在于第二个表中,但它应该在返回方法 InsertNewData 后处理(关闭),但在调用打开Insert的连接时,我收到以下消息:
连接未关闭。连接的当前状态是打开的。
我的代码是这样的:
public void InsertNewData(string operation)
{
DataTable dt = new DataTable();
try
{
if (operation!= string.Empty)
{
using (SqlConnection oconn = new SqlConnection(myDBone))
{
SqlCommand cmd = new SqlCommand();
SqlDataAdapter da = new SqlDataAdapter();
string query = "SELECT * FROM operations "+
"WHERE idoper=@id";
oconn.Open();
cmd = new SqlCommand(query, oconn);
cmd.Parameters.Add(new SqlParameter("@id", operation.ToString()));
da = new SqlDataAdapter(cmd);
da.Fill(dt);
}
if (dt.Rows.Count > 0)
{
using (SqlConnection con = new SqlConnection(myDBtwo))
{
SqlCommand com = new SqlCommand();
string query= "";
foreach (DataRow x in dt.Rows)
{
if (ValidateData(x) == false)
{
query= "INSERT INTO history(iddata,description, datehist ) "+
" VALUES(@id,@descrip,GETDATE())";
con.Open(); //Here throws the Exception error
com = new SqlCommand(query, con);
com.Parameters.Add(new SqlParameter("@id", x["idoper"].ToString()));
com.Parameters.Add(new SqlParameter("@descrip", x["description"] ));
com.ExecuteNonQuery();
}
}
}
}
}
}
catch (Exception x)
{
throw x;
}
}
public bool ValidateData(DataRow row)
{
bool exists= false;
string operation= row["idoper"].ToString();
string descrip= row["description"].ToString();
if (operation!= string.Empty && descrip!= string.Empty)
{
using (SqlConnection oconn = new SqlConnection(sqlrastreo))
{
SqlCommand cmd = new SqlCommand();
string query = "SELECT COUNT(*) FROM history "+
"WHERE iddata=@id AND description=@descrip";
oconn.Open();
cmd = new SqlCommand(query, oconn);
com.Parameters.Add(new SqlParameter("@id", operation));
com.Parameters.Add(new SqlParameter("@descrip", descrip));
int count = (int) cmd.ExecuteScalar();
if (count > 0)
exists= true;
}// Here it should be Disposed or closed the SqlConnection
}
return exists;
}
我做错了什么,因为它假设关闭另一个连接而另一个连接尚未打开?或者我还应该为块使用中的每个SqlConnection调用Close()方法吗?
更新: 我已经更改为最佳阅读代码和推荐语法的参数。
注意的 值和参数不是真实的,我的真实表描述有大约8个字段,但我只使用两个不是主键的参数进行验证,但考虑到我无法编辑表属性(仅具有该数据库的读取权限)。
更新2: 感谢 Sean Lange 的建议,使用存储过程(SP)同时验证和插入更好,更简单,所以我按照以下代码执行过程:
public void InsertNewData(string operation)
{
try
{
if(operation == string.Empty)
return;
using(SqlConnection con = new SqlConnection(myDBtwo))
{
con.Open();
var cmd = new SqlCommand("SP_InsertData", con);
cmd.Parameters.Add(new SqlParameter("@id", operation));
cmd.ExecuteNonQuery();
}
}
catch(Exception ex)
{ throw ex; }
}
然后在我的SP中我插入一个参数的select语句,以避免重复,并在一次性中执行:
CREATE PROCEDURE SP_InsertData @id VARCHAR(10)
AS
BEGIN
INSERT INTO History
SELECT O.idoper, O.description
FROM myDBone.dbo.operations O
LEFT JOIN History H
ON H.iddata = O.idoper AND H.description = O.description
WHERE O.idoper=@id AND H.iddata IS NULL
END
感谢您的支持,希望对某人有所帮助。
答案 0 :(得分:0)
首先你的代码编写得很糟糕,因为他们建议你不需要验证,尝试catch会为你做。在循环内打开一个连接(在你的情况下是foreach)将导致尝试打开已打开连接。这里的示例你可以做类似
的事情 query= "INSERT INTO history(iddata,description, datehist" VALUES(@id,@descrip,GETDATE())";
using (SqlConnection con = new SqlConnection(myDBtwo))
{
con.Open();
SqlCommand com = new SqlCommand(query,con);
foreach (DataRow x in dt.Rows)
{
com.Parameters.Add(new SqlParameter("@id", x["idoper"].ToString()));
com.Parameters.Add(new SqlParameter("@descrip", x["description"] ));
com.ExecuteNonQuery();
}
}
}