Fil*_*vić 6 .net c# ado.net connection-pooling sqlconnection
我有多个线程访问同一个数据库(具有相同的连接字符串).每个帖子:
使用下面的代码在需要时打开它自己的连接实例
try
{
wasOpened = connection.State == ConnectionState.Open;
if (connection.State == ConnectionState.Closed)
{
connection.Open();
}
}
catch (Exception ex)
{
throw new Exception(string.Format("Connection to data source {0} can not be established! Reason: {1} - complete stack {2}",
connection.Database, ex.Message, ex.StackTrace == null ? "NULL" : ex.StackTrace.ToString()));
}
Run Code Online (Sandbox Code Playgroud)到目前为止,我们已在2台服务器上测试了此代码,并且有一台服务器有时会在SqlConnection.Open方法中抛出异常.这是我们从catch块获得的异常消息:
无法建立与数据源xyz的连接!原因:操作无效.连接已关闭. - 完整的堆栈
在System.Data.SqlClient.SqlConnection.OpenConnection()
处于System.Data.SqlClient.SqlConnection.OpenConnection()
处于System.Data.SqlClient.SqlConnection.Open()
检查SqlConnection.GetOpenConnection方法显示innerConnection为null:
internal SqlInternalConnection GetOpenConnection()
{
SqlInternalConnection innerConnection = this.InnerConnection as SqlInternalConnection;
if (innerConnection == null)
{
throw ADP.ClosedConnectionError();
}
return innerConnection;
}
Run Code Online (Sandbox Code Playgroud)
我不清楚:为什么连接池有时会给我切断的连接(innerConnection == null)?
编辑#1:代码中没有静态属性 - 我们总是在适当时关闭连接,在我们的Close方法中使用wasOpened并且意味着:如果在调用Open时已经打开了连接,只需在关闭时保持打开,否则关闭它.但是,这与此问题中描述的问题无关(innerConnection == null).
编辑#2:服务器:SQL Server 2008 R2,Windows Server 2003.客户端:Windows Server 2003(代码在SSIS包自定义组件中运行).连接字符串:Data Source=server_name;Initial Catalog=db_name;Integrated Security=SSPI;Application Name=app_name
首先,仔细阅读:SQL Server连接池(ADO.NET)
我会为你引用最重要的部分(我认为):
为每个唯一连接字符串创建连接池.创建池时,会创建多个连接对象并将其添加到池中,以满足最小池大小要求.根据需要将连接添加到池中,直到指定的最大池大小(默认值为100).关闭或处置时,连接会释放回池中.
当请求SqlConnection对象时,如果可用的连接可用,则从池中获取它.要使用,连接必须是未使用的,具有匹配的事务上下文或与任何事务上下文无关,并且具有到服务器的有效链接.
连接池通过在连接释放回池中时重新分配连接来满足连接请求.如果已达到最大池大小且没有可用的可用连接,则请求将排队.然后,pooler尝试回收任何连接,直到达到超时(默认为15秒).如果在连接超时之前,pooler无法满足请求,则抛出异常.
我们强烈建议您在使用完毕后始终关闭连接,以便将连接返回到池中.您可以使用Connection对象的Close或Dispose方法,或打开C#中using语句内的所有连接,或Visual Basic中的Using语句来执行此操作.未显式关闭的连接可能不会添加或返回到池中.有关更多信息,请参阅using Statement(C#Reference)
简而言之:一旦你完成它们(fe via using-statement),不要在连接池的范围内偷猎并关闭连接.
既然你不想把你的DB-Class扔进垃圾桶,我建议要么增加最大池大小和/或超时,要么禁用池,看看会发生什么.
<add name="theConnectionString" connectionString="Data Source=(local);
Database=AdventureWorks; Integrated Security=SSPI;
Max Pool Size=200; Pooling=True; Timout=60" />
Run Code Online (Sandbox Code Playgroud)
您还应该尝试捕获此特定错误并清除所有连接池:
System.Data.SqlClient.SqlConnection.ClearAllPools();
Run Code Online (Sandbox Code Playgroud)
或者看看这些看起来很有希望的问题:
我有多个线程访问同一数据库(具有相同的连接字符串)。每个线程:
- 使用相同的连接字符串创建它自己的 SqlConnection 实例
- 使用下面的代码在需要时打开它自己的连接实例
如果您遇到随机出现的问题,在您的情况下,根据您显示的代码,您可能会遇到:
话虽这么说...
您应该将您的内容包含在声明SqlConnection中using。这样,当您的代码或线程完成连接时,连接将被关闭。
using (SqlConnection connection = new SqlConnection(connectionString))
{
//... stuff
}
Run Code Online (Sandbox Code Playgroud)
这样,连接就可以保证调用该Dispose()方法(Close()无论如何都会在内部调用)。这样,如果连接正在使用(可能正在使用),则可以将其返回到池中。
| 归档时间: |
|
| 查看次数: |
10162 次 |
| 最近记录: |