连接没有关闭。连接的当前状态是打开的。 C#

时间:2015-07-12 08:55:18

标签: c# asp.net

我一直在GetTotalMaterialCost中收到错误我已经检查了整件事。我甚至删除多余的con.Close但错误仍然会提示它。

decimal GetTotalMaterialCost()
{
    decimal total = 0;
    con.Open();
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = con;
    cmd.CommandText =
        "SELECT SUM(rm.Quantity * m.SellingPrice) AS TotalMaterialCost FROM Resource_Materials rm " +
        "JOIN Materials m ON m.MaterialID = rm.MaterialID " +
        "JOIN ProjectTasks t ON t.TaskID = rm.TaskID " +
        "WHERE t.TaskID=@TaskID HAVING COUNT (*) > 0";
    cmd.Parameters.AddWithValue("@TaskID", Request.QueryString["ID"].ToString());
    object data = cmd.ExecuteScalar();
    if (data == null)
        total = 0;
    else
        total = (decimal)cmd.ExecuteScalar();
    con.Close();
    return total;
}
protected void btnSave_Click(object sender, EventArgs e)
{
    con.Open();
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = con;
    cmd.CommandText = "UPDATE ProjectTasks SET Name=@Name, Description=@Description " +
        "WHERE TaskID=@TaskID; " +
        "SELECT TOP 1 TaskID FROM ProjectTasks ORDER BY TaskID DESC;";
    cmd.Parameters.AddWithValue("@Name", txtName.Text);
    cmd.Parameters.AddWithValue("@Description", txtDescription.Text);
    cmd.Parameters.AddWithValue("@TaskID", Request.QueryString["ID"].ToString());
    cmd.ExecuteNonQuery();

    cmd.CommandText = @"UPDATE Resource_Materials SET TaskID=@TaskID WHERE TaskID=0; " +
                        "UPDATE Resource_Equipments SET TaskID=@TaskID WHERE TaskID=0; " +
                        "UPDATE Resource_Vehicles SET TaskID=@TaskID WHERE TaskID=0; " +
                        "UPDATE Resource_Contractors SET TaskID=@TaskID WHERE TaskID=0; " +
                        "UPDATE Projects SET ActualCost=@ActualCost WHERE ProjectID=@ProjectID";
    cmd.Parameters.AddWithValue("@ProjectID", Request.QueryString["ID"].ToString());
    cmd.Parameters.AddWithValue("@ActualCost", GetAmount());
    con.Close();

    Helper.AddLog("1", "Add", "Assigned Resources to Task");
    Response.Redirect("~/Projects/Default.aspx");
}

Here is the link for my whole code as reference

所述错误在第679行

3 个答案:

答案 0 :(得分:3)

这通常是因为您使用全局连接对象并且代码中的某处未正确关闭连接。例如,在代码中的某处触发异常,在这种情况下忘记关闭连接。

分辨率始终相同。
不要保留全局连接对象 在需要时创建它并使用适当的语法将其销毁。

There is connection pooling infrastructure in ADO.NET设计用于在create/open/use/close方案中提供更好的效果。

decimal GetTotalMaterialCost()
{
    decimal total = 0;
    string query = @"SELECT SUM(rm.Quantity * m.SellingPrice) AS TotalMaterialCost 
                    FROM Resource_Materials rm 
                    JOIN Materials m ON m.MaterialID = rm.MaterialID 
                    JOIN ProjectTasks t ON t.TaskID = rm.TaskID
                    WHERE t.TaskID=@TaskID HAVING COUNT (*) > 0";

    using(SqlConnection con = new SqlConnection(....constringhere...)
    using(SqlCommand cmd = new SqlCommand(query, con))
    {
        con.Open();
        .....
     }
    return total;
}

通过这种方式,连接对象是本地的,using statement确保关闭并放置在右大括号中,即使遇到某种异常也是如此。

当然,应该在尝试访问数据库的每个点应用此模式,并且应删除全局连接对象。唯一可以保持全局的是连接字符串,为此还有一个更好的存储位置(IE.app.config ConnectionString部分)

表示您可能会遇到AddWithValue用法导致的错误。此方法定义参数的DataType,查看传递的值。您的TaskID字段似乎是一个整数,但您使用AddWithValue准备一个参数并传递一个字符串。因此查询将使用具有错误数据类型的参数。 我建议使用

cmd.Parameters.Add("@TaskID", SqlDbType.Int).Value = 
       Convert.ToInt32(Request.QueryString["ID"].ToString()));

最后,只是粗略地看一下你的代码,我建议改变你的Page_Load调用的方法来接收在Page_Load事件中直接打开的连接对象

if (!IsPostBack)
{
    using(SqlConnection con = new SqlConnection(....constringhere...)
    {
        GetProjectMaterials(con);
        GetProjectEquipments(con);
        GetProjectVehicle(con);
        GetProjectContractors(con);
        GetTasks(con,resourceID);
        GetMaterials(con);
        GetEquipments(con);
        GetVehicles(con);
        GetLContractors(con);
    }
}

当然,您还需要更改调用这些方法来传递连接的其他方法,但如果我没有错,则必须在这些调用方中建立连接。

答案 1 :(得分:0)

我建议你使用局部变量连接"使用"因为.NET SQL提供程序将为您和"使用"将确保您的连接正确关闭和处置。所以你的代码看起来像:

    decimal GetTotalMaterialCost()
    {
        decimal total = 0;
        using (var con = new SqlConnection(/*connection string if not configured via web.config*/))
        {
            con.Open();
            using (SqlCommand cmd = new SqlCommand())
            {
                cmd.Connection = con;
                cmd.CommandText =
                    "SELECT SUM(rm.Quantity * m.SellingPrice) AS TotalMaterialCost FROM Resource_Materials rm " +
                    "JOIN Materials m ON m.MaterialID = rm.MaterialID " +
                    "JOIN ProjectTasks t ON t.TaskID = rm.TaskID " +
                    "WHERE t.TaskID=@TaskID HAVING COUNT (*) > 0";
                cmd.Parameters.AddWithValue("@TaskID", Request.QueryString["ID"].ToString());
                object data = cmd.ExecuteScalar();
                if (data == null)
                    total = 0;
                else
                    total = (decimal)cmd.ExecuteScalar();
            }
        }
        return total;
    }

答案 2 :(得分:0)

您正在调用cmd.ExecuteScalar()两次而不重置它。设置total变量的行应为total = (decimal) data;。毕竟,你已经有了答案,为什么不使用它而不是重新执行代码?