【问题标题】:Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool.超时已过。在从池中获取连接之前超时时间已过。
【发布时间】:2014-07-07 01:36:15
【问题描述】:

我正在开发一个使用 WebApiAngularJS 的应用程序。在花了一些时间申请后,我得到了这个例外。我在此应用中使用 EntityFramework

"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."

堆栈跟踪

at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
↵ at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)

【问题讨论】:

  • 没有你的代码,很难说哪里出了问题。如果我不得不猜测,我会说你需要使用 using 块。
  • 是的,我没有使用“使用声明”

标签: c# entity-framework


【解决方案1】:

关闭你的数据库连接(这很重要)。

SqlConnection myConnection = new SqlConnection(ConnectionString);
try
{
     conn.Open();
     someCall (myConnection);
}
finally
{
     myConnection.Close();                
}

using (SqlConnection myConnection = new SqlConnection(ConnectionString))
{
     myConnection.Open();
     someCall(myConnection);
}

检查有多少用户连接到您的数据库以及查询超时。如果你有很长时间执行查询,也要检查一下。

也许,重复的问题:

How can I solve a connection pool problem between ASP.NET and SQL Server?

When does Entity Framework open and close Database Connections?

【讨论】:

  • 他没有打开或创建连接;实体框架在幕后隐含地做这件事。如果有呼叫new SqlConnection,那就太好了,因为那样他就可以using.Dispose
【解决方案2】:

我刚刚遇到了同样的问题。我最终使用了这样的模式,似乎解决了这个问题:

using (SqlConnection con = new SqlConnection(strCon)) 
{
    using (SqlCommand cmd = new SqlCommand(strCmdText, con)) 
    {
        con.Open();
        using (SqlDataReader dr = cmd.ExecuteReader())
         {
              //do stuff;
              dr.Close();
         }
     }
     con.Close();
}

这似乎解决了我的问题。 DataReader.Close() 是做到这一点的钉子。似乎 MS 应该改变他们的建议,因为我在他们的网站上发现了建议不要使用 try { } finally { con.Close(); } 模式。我没有明确地尝试这个,因为这种模式在我们整个数据库层中相当普遍,并且想要找到更接近的东西。

我希望这对某人有所帮助。

【讨论】:

    【解决方案3】:

    请尝试以下方法

    1. 始终在 finally 块中关闭您的连接

    2. 增加连接字符串中的池大小 string connectionString = "数据源=localhost;初始目录=Northwind;" + "集成安全=SSPI;最小池大小=10;最大池大小=100";

                                    or 
      
    3. 根本不使用池化 string connectionString = "数据源=localhost;初始目录=Northwind;" + "Integrated Security=SSPI; Pooling=false;";

    【讨论】:

    • 当我尝试得到错误:不支持关键字:'&pooling'。
    【解决方案4】:

    建议在 SqlConnection 和 SqlCommand 对象周围使用 using 语句。

    请注意,如果您有一个函数在 SqlDataReader 循环中使用 yield return 返回一个 IEnumerable,那么这不是推荐的模式。这样做会在执行数据读取器之前关闭与数据库的连接。

    改为将 CommandBehavior.CloseConnection 参数应用于 ExecuteReader 调用。

    【讨论】:

      【解决方案5】:

      有点老了,很抱歉挖了这个,但是这周在我们的工作中发生了:

      正如@sohail naseer 回答的那样,您的连接没有关闭,或者您的数据类使用不正确:

      如果您循环 105 次,并且在每个循环中声明一个新数据对象并使用它查询数据库,那么即使您关闭并处置对象,您也将创建 105 个连接(从而破坏您的 100 max allowed )正确地,SQL 仍然需要时间将该连接重新分配给新用户。

      【讨论】:

        【解决方案6】:

        强制垃圾收集器调用:

        System.GC.Collect()
        

        【讨论】:

        • 这适用于我的情况。但我更喜欢另一种选择:不在连接字符串中使用连接池 (...; Pooling=false;...)。因此,我可以将垃圾收集留在系统级别本身。
        • 请,请,请!不要强制执行 GC,除非完全确定这是一个好主意(有可能,但不是)。更多信息请参考this answer
        猜你喜欢
        • 2014-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-01
        相关资源
        最近更新 更多