超时过期异常;无法找到哪个连接保持打开状态或者是否存在其他问题

发布于 2024-12-27 03:54:44 字数 2265 浏览 5 评论 0原文

我收到“超时已过期。从池中获取连接之前超时时间已过。发生这种情况的原因可能是所有池连接都在使用中并且已达到最大池大小。”错误,但是找不到问题出在哪里。请一点帮助。 :)

public static void Update(string p, int c)
    {
        using (SqlConnection conn = new SqlConnection("ConnectionString"))
        {
            SqlCommand cmd = new SqlCommand();
            SqlDataReader myRdr;

            cmd.Connection = conn;
            cmd.CommandText = "SOME SQL QUERY @parameter";
            cmd.CommandType = CommandType.Text;
            cmd.Parameters.Add("@parameter", SqlDbType.NVarChar, 10).Value = p;

            conn.Open();
            myRdr = cmd.ExecuteReader();

            if (myRdr.HasRows)
            {
                while (myRdr.Read())
                {
                    //do something using myRdr data
                }
                myRdr.Close();
                cmd.Dispose();

                foreach (DataRow r in dt.Rows)
                {
                    SqlCommand cmd1 = new SqlCommand();

                    cmd1.Connection = conn;
                    cmd1.CommandText = "SOME SQL QUERY @parameter";
                    cmd1.CommandType = CommandType.Text;
                    cmd1.Parameters.Add("@parameter", SqlDbType.NVarChar, 10).Value = r["SomeData"];

                    myRdr = cmd1.ExecuteReader();
                    myRdr.Read();

                    //do something with myRdr data

                    myRdr.Close();
                    cmd1.Dispose();

                    int a = Convert.ToInt32(r["SomeData"]) - Convert.ToInt32(r["SomeData1"]);

                    if (a >= 0)
                    {
                        //do something
                    }
                    else
                    {
                        //do something else and runn the Update() again with some other parameters

                        Update(x, y); //I think here is some problem...
                                      //because when this condition is not met and program 
                                      //does not need to run Update() again, it goes OK and I get no error
                    }
                }
            }
            else
            {
                myRdr.Close();
                cmd.Dispose();
            }
        }
    }

I'm getting "Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached." error, but can't find where is the problem. Little help, please. :)

public static void Update(string p, int c)
    {
        using (SqlConnection conn = new SqlConnection("ConnectionString"))
        {
            SqlCommand cmd = new SqlCommand();
            SqlDataReader myRdr;

            cmd.Connection = conn;
            cmd.CommandText = "SOME SQL QUERY @parameter";
            cmd.CommandType = CommandType.Text;
            cmd.Parameters.Add("@parameter", SqlDbType.NVarChar, 10).Value = p;

            conn.Open();
            myRdr = cmd.ExecuteReader();

            if (myRdr.HasRows)
            {
                while (myRdr.Read())
                {
                    //do something using myRdr data
                }
                myRdr.Close();
                cmd.Dispose();

                foreach (DataRow r in dt.Rows)
                {
                    SqlCommand cmd1 = new SqlCommand();

                    cmd1.Connection = conn;
                    cmd1.CommandText = "SOME SQL QUERY @parameter";
                    cmd1.CommandType = CommandType.Text;
                    cmd1.Parameters.Add("@parameter", SqlDbType.NVarChar, 10).Value = r["SomeData"];

                    myRdr = cmd1.ExecuteReader();
                    myRdr.Read();

                    //do something with myRdr data

                    myRdr.Close();
                    cmd1.Dispose();

                    int a = Convert.ToInt32(r["SomeData"]) - Convert.ToInt32(r["SomeData1"]);

                    if (a >= 0)
                    {
                        //do something
                    }
                    else
                    {
                        //do something else and runn the Update() again with some other parameters

                        Update(x, y); //I think here is some problem...
                                      //because when this condition is not met and program 
                                      //does not need to run Update() again, it goes OK and I get no error
                    }
                }
            }
            else
            {
                myRdr.Close();
                cmd.Dispose();
            }
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏天碎花小短裙 2025-01-03 03:54:44

您应该考虑将调用移至外部 using() 块之外的某个位置。

从内部 using 调用它意味着您正在建立与同一数据库的另一个连接,而无需首先释放外部连接。如果您收到大量递归调用,那么您将很快耗尽可用连接。

一般来说,在处理数据库的代码部分中使用递归调用被认为是非常糟糕的做法。

如果您确实需要在这里进行递归,那么它仍然应该在外部 using 之外完成。我建议将您的 x,y 缓存在某种集合中,并通过在 using< 之外遍历此集合来发出对 Update(x,y) 的调用/code> 块,如下所示:

public static void Update(string p, int c)
{
    // I'd suggest Dictionary, but don't know whether your strings are unique
    var recursionParameters = new List<KeyValuePair<string, int>>(); 

    using (SqlConnection conn = new SqlConnection("ConnectionString"))
    {
        ...
                    //do something else and runn the Update() again with some other parameters

                    //Update(x, y); Don't do it here! Instead:
                    recursionParameters.Add(new KeyValuePair<string, int>(x,y));
        ...
    }
    foreach (var kvp in recursionParameters
    {
        Update(kvp.Key, kvp.Value)
    }
}

You should cosider moving your call to Update(x,y) somewhere outside the outer using() block.

Calling it from the inside using means you're establishing another connection to the same database without first freeing the outer one. If you get number of recursive calls then you'll run out of free connections VERY quickly.

In general, using recursion calls in parts of code dealing with databases is considered a very bad practice.

If you REALLY need this recursion here then still it should be done outside the outer using. I'd suggest caching your x,y in some kind of collection and issuing the calls to Update(x,y) by traversing this collection outside the using block, like this :

public static void Update(string p, int c)
{
    // I'd suggest Dictionary, but don't know whether your strings are unique
    var recursionParameters = new List<KeyValuePair<string, int>>(); 

    using (SqlConnection conn = new SqlConnection("ConnectionString"))
    {
        ...
                    //do something else and runn the Update() again with some other parameters

                    //Update(x, y); Don't do it here! Instead:
                    recursionParameters.Add(new KeyValuePair<string, int>(x,y));
        ...
    }
    foreach (var kvp in recursionParameters
    {
        Update(kvp.Key, kvp.Value)
    }
}
久光 2025-01-03 03:54:44

发生异常时,您的Reader可能不会关闭。用 try finally 块将其包围,因此当您遇到异常时,您的阅读器将在 finally 语句中关闭。

try
{  
    myRdr = cmd.ExecuteReader();
    // do some other stuff
}
catch(SqlException)
{
    // log the exception or deal with ex.

}
finally
{
    myRdr.Close(); // you can be sure it will be closed even on exception

}

Your Reader may not be closed when exception occurs. Surround it with try finally block, so when you meet exception your reader will be closed on finally statement.

try
{  
    myRdr = cmd.ExecuteReader();
    // do some other stuff
}
catch(SqlException)
{
    // log the exception or deal with ex.

}
finally
{
    myRdr.Close(); // you can be sure it will be closed even on exception

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文