在上一篇中简单讨论了SqlConnection的正确使用方式,顺带浅谈了一下连接池,不小心带出了一个问题:SqlConnection的Close和Dispose方法执行之后,该连接对象是不是真的放回到池中并且可以复用?
今天上午我抽空看了一下SqlConnection的Close和Dispose的IL代码,看完之后并没有直接打消我的疑惑,反而让我更加不确定。
今晚又仔细看了下文中的回复,非常汗颜,感觉自己基础还是不太扎实,同时又有点小怀疑。
这里尤其感谢园友rdlc2和荒原上的军旗的回复,他们的不吝赐教直接给了我启发,今晚又写了一段简单的测试代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
static
void
Execute()
{
SqlConnection conn =
new
SqlConnection(sqlConnString);
conn.Open();
Console.WriteLine(
"Current Connection State:{0}"
, conn.State);
conn.Close();
Console.WriteLine(
"Current Connection State:{0}"
, conn.State);
Thread.Sleep(100);
conn.Open();
Console.WriteLine(
"Current Connection State:{0}"
, conn.State);
conn.Close();
Console.WriteLine(
"Current Connection State:{0}"
, conn.State);
Thread.Sleep(100);
conn.Open();
Console.WriteLine(
"Current Connection State:{0}"
, conn.State);
conn.Dispose();
Console.WriteLine(
"Current Connection State:{0}"
, conn.State);
Console.WriteLine(
"Current Connection String:{0}"
, conn.ConnectionString);
Thread.Sleep(100);
try
{
//conn.ConnectionString = sqlConnString; //加上这一行,Open可以正常执行
conn.Open();
//异常:ConnectionString没有初始化
Console.WriteLine(
"Current Connection State:{0}"
, conn.State);
}
catch
(Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
if
(conn.State == ConnectionState.Open)
{
conn.Close();
}
Console.WriteLine(
"Current Connection State:{0}"
, conn.State);
}
}
|
执行结果正如注释所写,在调用Dispose之后,SqlConnection的ConnectionString属性变为String.Empty了。
而在MSDN上,关于连接池的创建和分配是这么说的:
在初次打开连接时,将根据完全匹配算法创建连接池,该算法将池与连接中的连接字符串关联。每个连接池都与一个不同的连接字符串相关联。打开新连接时,如果连接字符串并非与现有池完全匹配,将创建一个新池。按进程、应用程序域、连接字符串以及 Windows 标识(在使用集成的安全性时)来建立池连接。连接字符串还必须是完全匹配的;按不同顺序为同一连接提供的关键字将分到单独的池中。
也就是说,连接池的一个重要特性是根据连接字符串来划分该连接到底属于哪一个池。那么对于Dispose执行后连接字符串为空的连接对象它会归到哪一个池中呢?也许这个对象是真的放回到某一个池中,但是到底微软的连接池做了怎样的内部处理,比如连接字符串是怎么重新分配的呢?Dispose真的和Close方法执行效果一样吗?
反正我现在还是将信将疑。
说出你的看法吧。
本文转自JeffWong博客园博客,原文链接:http://www.cnblogs.com/jeffwongishandsome/archive/2011/08/10/2134317.html,如需转载请自行联系原作者