题外话
今天同事问我.Net的数据库连接有没有连接池的概念。我根据脑海里一点模糊的印象回答他.Net是自己实现了连接池,不需要手工再实现一遍。
后来回家确认了一下,原来我的这点印象来自《C#和.Net核心技术》中一小段数据库连接池的介绍。可能当时也只是知道.Net自己实现了不需我们再手工实现,另外就是.Net是通过连接字符串的不同来区分不同的连接的。所以当时就放在一边不管了,呵呵,真是懒惰啊。
这次新问题是,既然.Net底层实现了连接池,当在程序中显式调用close()方法时,连接会不会关掉呢?
《C#和.Net核心技术》中也只有500字不到的一点说明,没有说清楚这点,于是找了MSDN。一切如“众里寻她千百度,蓦然回首,那人却在灯火阑珊处。”一般,终于找到了看明白了弄清楚了。
正文
连接池减少新连接需要打开的次数。池进程保持物理连接的所有权。通过为每个给定的连接配置保留一组活动连接来管理连接。只要用户在连接上调用 Open,池进程就会检查池中是否有可用的连接。如果某个池连接可用,会将该连接返回给调用者,而不是打开新连接。应用程序在该连接上调用 Close 时,池进程会将连接返回到活动连接池集中,而不是真正关闭连接。连接返回到池中之后,即可在下一个 Open 调用中重复使用。
只有配置相同的连接可以建立池连接。ADO.NET 同时保留多个池,每个配置一个池。连接由连接字符串以及 Windows 标识(在使用集成的安全性时)分为多个池。
池连接可以大大提高应用程序的性能和可缩放性。默认情况下,ADO.NET 中启用连接池。除非显式禁用,否则,连接在应用程序中打开和关闭时,池进程将对连接进行优化。还可以提供几个连接字符串修饰符来控制连接池的行为。
池的创建和分配
在初次打开连接时,将根据完全匹配算法创建连接池,该算法将池与连接中的连接字符串关联。每个连接池与不同的连接字符串关联。打开新连接时,如果连接字符串并非与现有池完全匹配,将创建一个新池。按进程、按应用程序域、按连接字符串以及(在使用集成的安全性时)按 Windows 标识来建立池连接。
在以下 C# 示例中创建了三个新的
SqlConnection
对象,但是管理时只需要两个连接池。注意,根据为 Initial Catalog
分配的值,第一个和第二个连接字符串有所不同。
using
(SqlConnection connection
=
new
SqlConnection(
"
Integrated Security=SSPI;Initial Catalog=Northwind
"
))
{
connection.Open();
//
Pool A is created.
}
using
(SqlConnection connection
=
new
SqlConnection(
"
Integrated Security=SSPI;Initial Catalog=pubs
"
))
{
connection.Open();
//
Pool B is created because the connection strings differ.
}
using
(SqlConnection connection
=
new
SqlConnection(
"
Integrated Security=SSPI;Initial Catalog=Northwind
"
))
{
connection.Open();
//
The connection string matches pool A.
}
我们建议您在使用完连接时一定要关闭连接,以便连接可以返回池。要关闭连接,可以使用 Connection 对象的 Close 或 Dispose 方法,也可以通过在 C# 的 using 语句中或在 Visual Basic 的 Using 语句中打开所有连接。不是显式关闭的连接可能不会添加或返回到池中。