在另一个块中使用SqlConnection块时打开连接

时间:2018-04-18 20:33:24

标签: c# sql-server using

在项目中,我调用一个方法来使用 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

感谢您的支持,希望对某人有所帮助。

1 个答案:

答案 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();
                    }
                }
            }