c#

位置:IT落伍者 >> c# >> 浏览文章

.NET程序中对连接池的管理方法


发布日期:2021年12月31日
 
.NET程序中对连接池的管理方法

对于访问量高的系统每次创建一个连接都会消耗一定的资源我们可以事先创建好一定数量的连接放入连接池中提供给用户使用用户使用完后把连接返回连接池这里我就来说说连接池的管理

首先让我们来看看连接池的概念

连接池允许应用程序从连接池中获得一个连接并使用这个连接而不需要为每一个连接请求重新建立一个连接一旦一个新的连接被创建并且放置在连接池中应用程序就可以重复使用这个连接而不必实施整个数据库连接创建过程

当应用程序请求一个连接时连接池为该应用程序分配一个连接而不是重新建立一个连接当应用程序使用完连接后该连接被归还给连接池而不是直接释放

优点

使用连接池的最主要的优点是性能

创建一个新的数据库连接所耗费的时间主要取决于网络的速度以及应用程序和数据库服务器的(网络)距离而且这个过程通常是一个很耗时的过程而采用数据库连接池后数据库连接请求可以直接通过连接池满足而不需要为该请求重新连接认证到数据库服务器这样就节省了时间

缺点

数据库连接池中可能存在着多个没有被使用的连接一直连接着数据库(这意味着资源的浪费)

ps这必须要求开发人员在开发时估计这个系统最大提供的数量是多少

池的创建和分配

当连接打开时将根据一种精确的匹配算法来创建连接池该算法会使连接池与连接中的字符串相关联每个连接池都与一个不同的连接字符串相关联当新连接打开时如果连接字符串不精确匹配现有池则将创建一个新池

在以下示例中将创建三个新的 SqlConnection 对象但只需要使用两个连接池来管理这些对象请注意第一个和第二个连接字符串的差异在于为 Initial Catalog 分配的值

SqlConnection conn = new SqlConnection();

connConnectionString = Integrated Security=SSPI;Initial Catalog=northwind;

connOpen();

// 连接池A创建了

SqlConnection conn = new SqlConnection();

connConnectionString = Integrated Security=SSPI;Initial Catalog=pubs;

connOpen();

// 连接池B创建了因为ConnectionString与A不匹配

SqlConnection conn = new SqlConnection();

connConnectionString = Integrated Security=SSPI;Initial Catalog=northwind;

connOpen();

// 使用A的连接池因为ConnectionString与A匹配

连接池一旦创建直到活动进程终止时才会被毁坏非活动或空池的维护只需要最少的系统开销

连接的添加

连接池是为每个唯一的连接字符串创建的当创建一个池后将创建多个连接对象并将其添加到该池中以满足最小池大小的要求连接将根据需要添加到池中直至达到最大池大小

当请求 SqlConnection 对象时如果存在可用的连接则将从池中获取该对象若要成为可用连接该连接当前必须未被使用具有匹配的事务上下文或者不与任何事务上下文相关联并且具有与服务器的有效链接

如果已达到最大池大小且不存在可用的连接则该请求将会排队当连接被释放回池中时连接池管理程序通过重新分配连接来满足这些请求对 Connection 调用 Close 或 Dispose 时连接被释放回池中

警告 建议使用完 Connection 后始终将其关闭以便连接可以返回到池中这可以使用 Connection 对象的 Close 或 Dispose 方法来实现不是显式关闭的连接可能不会添加或返回到池中例如如果连接已超出范围但没有显式关闭则仅当达到最大池大小而该连接仍然有效时该连接才会返回到连接池中

注意 不要在类的 Finalize 方法中对 ConnectionDataReader 或任何其他托管对象调用 Close 或 Dispose在终结器中仅释放类直接拥有的非托管资源如果类不拥有任何非托管资源则不要在类定义中包含 Finalize 方法有关更多信息请参见垃圾回收编程

连接的移除

如果连接生存期已过期或者连接池管理程序检测到与服务器的连接已断开连接池管理程序将从池中移除该连接请注意只有在尝试与服务器进行通信后才可以检测到这种情况如果发现某连接不再连接到服务器则会将其标记为无效连接池管理程序会定期扫描连接池查找已释放到池中并标记为无效的对象找到后这些连接将被永久移除

如果存在与已消失的服务器的连接那么即使连接池管理程序未检测到已断开的连接并将其标记为无效仍有可能将此连接从池中取出当发生这种情况时将生成异常但是为了将该连接释放回池中仍必须将其关闭

字符串关键字

Connection Lifetime 当连接返回到池中时将对它的创建时间和当前时间进行比较如果时间间隔超过由 Connection Lifetime 指定的值(以秒为单位)则会毁坏该连接在聚集配置中可以使用它来强制在运行服务器和刚联机的服务器之间达到负载平衡

如果值为零 ()则将使池连接具有最大的超时期限

Connection Reset true 确定在从池中移除数据库连接时是否将其重置对于 Microsoft SQL Server 版本 如果设置为 false将避免在获取连接时经历一个额外的往返过程但必须注意的是连接状态(如数据库上下文)不会被重置

Enlist true 当为 true 时如果存在事务上下文池管理程序将自动在创建线程的当前事务上下文中登记连接

Max Pool Size 池中允许的最大连接数

Min Pool Size 池中维护的最小连接数

Pooling true 当为 true 时将从相应的池中取出连接或者在必要时创建连接并将其添加到相应的池中

实例代码

namespace HowToSamplesADONET

{

using System;

using SystemDataSqlClient;

public class connectionpooling

{

public static void Main()

{

connectionpooling myconnectionpooling = new connectionpooling();

myconnectionpoolingRun();

}

public void Run()

{

try

{

String connString;

// Specification in the connection string:

// Please note: Pooling is implicit you automatically get it unless you disable it

//Therefore true is the default for the pooling keyword (pooling=true)

// Connection Reset:False

// Connection Lifetime:

// Enlist:true

// Min Pool Size:

// Max Pool Size:

connString = server=(local)\\NetSDK;Trusted_Connection=yes;database=northwind; +

connection reset=false; +

connection lifetime=; +

min pool size=; +

max pool size=;

SqlConnection myConnection = new SqlConnection(connString);

SqlConnection myConnection = new SqlConnection(connString);

SqlConnection myConnection = new SqlConnection(connString);

// Open two connections

ConsoleWriteLine (打开两个连接);

myConnectionOpen();

myConnectionOpen();

// Now there are two connections in the pool that matches the connection string

// Return the both connections to the pool

ConsoleWriteLine (将两个连接都返回到池中);

myConnectionClose();

myConnectionClose();

// Get a connection out of the pool

ConsoleWriteLine (从池中打开一个连接);

myConnectionOpen();

// Get a second connection out of the pool

ConsoleWriteLine (从池中打开第二个连接);

myConnectionOpen();

// Open a third connection

ConsoleWriteLine (打开第三个连接);

myConnectionOpen();

// Return the all connections to the pool

ConsoleWriteLine (将所有三个连接都返回到池中);

myConnectionClose();

myConnectionClose();

myConnectionClose();

}

catch (Exception e)

{

// Display the error

ConsoleWriteLine(eToString());

}

}

}

}

上一篇:简单介绍.Net远程方法调用研究

下一篇:代码最优化.NET中的内存管理