超时错误。在从池中获取连接之前,已经超过了超时时间。

10

我正在使用 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)

3
没有您的代码,很难说出问题出在哪里。如果我必须猜测的话,我会建议您使用using块。 - nvoigt
是的,我没有使用“using语句”。 - Ravi Mittal
6个回答

15

关闭数据库连接(这非常重要)。

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

检查连接到你的数据库的用户数量和查询超时时间。还要检查是否存在执行时间长的查询。

也许是重复的问题:

如何解决ASP.NET和SQL Server之间的连接池问题?

Entity Framework何时打开和关闭数据库连接?


4
他并没有打开或创建连接;实体框架在幕后隐式地执行这个操作。如果有一个对new SqlConnection的调用,那就太好了,因为这样他就可以使用using或者.Dispose来进行处理。其中,原文中的“was”是虚拟语气,表示一种假设和希望,应该翻译为“如果有”。 - Ian Boyd

5

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

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()就是关键。看起来微软应该改变他们的建议,因为我在他们的网站上发现这个模式被广泛推荐,不要使用try { } finally { con.Close(); }模式。虽然整个数据库层都存在这种模式,但我没有明确尝试过,希望能找到更接近的解决方案。
希望这能帮助到某些人。

5
请尝试以下几点:
1. 在finally块中始终关闭您的连接。 2. 像在连接字符串中一样增加连接池大小。 ```csharp string connectionString = "Data Source=localhost; Initial Catalog=Northwind;Integrated Security=SSPI; Min Pool Size=10; Max Pool Size=100"; ``` 3. 或者,完全不使用连接池。 ```csharp string connectionString = "Data Source=localhost; Initial Catalog=Northwind;Integrated Security=SSPI; Pooling=false;"; ```

当我尝试时,出现了错误:不支持的关键字:“&pooling”。 - ItaiRoded

2

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

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

相反,将 CommandBehavior.CloseConnection 参数应用于 ExecuteReader 调用。


1
抱歉挖掘这个有点旧的话题,但这周我们在工作中遇到了同样的问题:
要么像@sohail naseer所说,你的连接没有关闭,要么你有一个数据类没有正确使用:
如果你循环105次,在每次循环中声明一个新的数据对象并查询数据库,即使你正确地关闭和处理这些对象,你仍会创建105个连接(超过了允许的最大100个),即使你关闭并正确处理对象,SQL仍需要时间将该连接重新分配给新用户。

-1

强制垃圾回收调用:

System.GC.Collect()

这对我的情况起作用了。但我更喜欢另一种选择:在连接字符串中不使用连接池(...; Pooling=false;...)。这样,我可以将垃圾回收留在系统级别。 - Bimal Poudel
3
请务必确保完全确定是个好主意后再强制执行垃圾回收(很可能不是)。有关更多信息,请参阅此答案 - Nahuel Ianni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接