ADO.NET,连接\连接池问题
问:在 ADO.NET 中,一个进程可以创建多少连接池?我知道,如果我有 n 个连接字符串的话,将有 n 个池。但是这个 n 是否具有最大值呢?另外,MSDN 文章中指出,一旦创建了连接池,那么这些连接池在活动进程结束之前就不会被破坏。非活动池或空池的维护涉及的系统开销很小。非活动池是否会被剪除?
答:如果您问可以创建多少池的话,答案是每个应用程序域使用的每个连接字符串一个池。对于集成的安全连接,会根据不同用户的数量而创建子池。如果您在某个特定的应用程序域中使用 n 个连接字符串,则将拥有 n 个池。连接池是以每个应用程序域为基础创建的,而不是根据每个进程创建的。池是在有用户连接请求的需要时创建的。还有一个逻辑用于剪除池,甚至在用户没有指定其他设置的情况下,可在一段非活动时间之后删除这些池。
可以创建的池数量没有上限。您提到的 MSDN 注释对于 Microsoft .NET Framework 1.0 和 1.1 是正确的。如果您没有指定最小池大小的话,这些池在非活动时间之后将一直保留,即使它们是空的也是如此。在 .NET Framework 2.0 中,一段非活动时间之后,Framework 将删除该池。
问:如果某个应用程序同时建立了 50 个与 SQL Server™ 的连接,则连接池中将具有 50 个连接。何时从池中将它们删除?如果它们的 ConnectionLifetime 为 0,文章中说明此设置表示使用最长的连接生命周期,那么这个生命周期是多长?
答:删除池中连接背后的逻辑没有记录,但是这并没有阻止人们发现该逻辑的尝试,以及有关此类文章的编写。最好的一篇文章可能是 SqlClient Connection Pooling Exposed - Reflection allows .NET developers to peer into the internals of SqlClient。您还可以查看下列 blog:ADO.NET The misunderstood "Connection Lifetime" managed pooler connection string keyword.
基本的理念是,在池中保持闲置状态的连接将在大约 4 分钟和 8 分钟之间一个任意的时间内进行清除,具体取决于实施细节。正如前面提到的那篇文章所讲述的那样,如果不使用反射,您根本不可能更改该默认值。
设置了最小连接池大小的连接的真正行为与没有此设置的连接相同。关闭该连接时,会检查该连接生命周期,并且该连接将被处置。托管的池将注意到您已经小于最小池大小,因此会在后台线程上打开一个新连接。连接生命周期与连接池闲置时间无关。将其设置为 0 相当于设置为 int32.MaxValue 的最大值,2147483647 秒。
问:ADO.NET 是否会执行任何操作来保护传递到 SQLConnection 对象的连接字符串参数的安全?我担心的是公开连接字符串的内存转储问题。对连接字符串执行比较,以确定是否可以使用池中的连接时,是否会传递真正的字符串?
答:首先,应该注意,有关公开连接字符串的担心并非 ADO.NET 所特有的;这对于所有数据库访问技术来说都是一个合理的担心。实际上没有什么方法可用来保护密码不会被对 ADO.NET 应用程序具有管理员权限的用户看到。他可以从 .exe 文件、内存转储、通过从网络进行数据包探测,通过欺骗服务器信息等方式来获取密码。
一个很好的解决方案是使用集成安全。这就意味着,您的程序可以执行经过身份验证的用户在没有您程序的情况下有权限执行的任何操作。如果使用集成安全,在此过程中将不会显示任何密码。
作为在连接字符串中使用密码的众多危险的一个示例,请采用此方案。首先,请使用包含密码的连接字符串调用 SqlConnection.Open。第二,SqlConnection 尽快对该密码进行内部加密。但是,即使使用此设计,在垃圾收集发生之前的进程内存转储仍会向您显示调用 SqlConnection.Open 时所使用的字符串对象(连接字符串)。因此,无论 SqlConnection 执行什么操作,它都无法隐藏此连接字符串的内容。SqlConnection 甚至无法擦除传入连接字符串中的数据,因为字符串在 .NET 中是不可变的。有关在基于 .NET 的应用程序中保护字符串安全的详细信息,请参阅本期 MSDN Magazine 中的 Security Briefs,尤其是有关 System.Security 和新 SecureString 类的部分。
第二个选择是完全向用户隐藏数据库(如使用 Web 服务解决方案),以便该数据库只能由 Web 服务器访问。
问:我想知道如何使得页上的菜单项不会出现在正在显示的图后面?该图是一个包含在 <DIV> 标记中的 flash 对象。是否应该使用 Z-索引?当我在主菜单上移动鼠标时,应该显示菜单项,但是其中某些菜单项总是会隐藏在该图之后。
答:在 <DIV> 元素上设置 Z-索引属性不会有所帮助,这是因为 Flash 控件是一个有窗口的元素,不允许其他 DHTML 内容置于它上面的层中。您可能能够将您的菜单更改为使用 createPopup,这样就会位于另一个有窗口对象的上面了。但是,请注意,辅助功能应该仍然能够使用这些菜单项。有关如何完成上述任务的详细信息,请参阅 createPopup Method。