作为单元测试的一部分,我们在测试开始时恢复空白数据库。然后,单元测试通过调用Web服务(托管在Visual Studio ASP.NET主机中)来执行测试。
第一次运行单元测试时,这对我们来说很好,但是如果重新运行它们而不重新启动Web服务,则会引发异常,因为所有连接都已作为还原的一部分重置。
下面的代码模拟了发生的事情:
static void Main(string[] args)
{
DoDBStuff();
new Server("localhost").KillAllProcesses("Test");
DoDBStuff();
}
private static void DoDBStuff()
{
string constr = "Data Source=localhost;Initial Catalog=Test;Trusted_Connection=Yes";
using (SqlConnection con = new SqlConnection(constr))
{
con.Open();
using (SqlCommand cmd = new SqlCommand("SELECT TOP 1 id FROM sysobjects", con))
{
int? i = cmd.ExecuteScalar() as int?;
}
}
}
除了KillAllProcesses之外的所有代码都在Web服务的进程中运行,而KillAllProcess在单元测试进程中运行。通过重新启动SQL服务器可以实现同样的目的。
我们遇到的问题是webservices不知道什么时候连接被杀死,只是从连接池中选择“坏”连接。此外,连接的创建和命令的执行在应用程序中分开了几层。
如何在执行命令之前检测到连接是“坏”,而不会对应用程序的性能产生很大影响?
答案 0 :(得分:2)
在终止SQL Server之后,您的连接池将包含与旧的SQL Server实例的过时连接。
重新启动SQL Server后,可以调用SqlConnection.ClearAllPools()来清除池中的陈旧连接,例如:
static void Main(string[] args)
{
DoDBStuff();
new Server("localhost").KillAllProcesses("Test");
SqlConnection.ClearAllPools();
DoDBStuff();
}
NB ClearAllPools方法是在.NET 2.0中引入的
答案 1 :(得分:1)
出于单元测试目的,您可以调整连接池超时吗?这样,连接变得陈旧,并且它们在结账/编译过程中会过期,并且在实际的单元测试运行时会全部清除?
或者,作为另一种选择,您是否可以编写首先执行的单元测试并调用刷新现有连接池的Web服务?它会强制任何新的数据请求生成新的数据库连接,这不会导致异常。根据MSDN:
ADO.NET 2.0引入了两种新方法 清除池:ClearAllPools和 ClearPool。 ClearAllPools清除了 给定提供程序的连接池, 和ClearPool清除连接 与a关联的池 具体连接。如果有 在使用时使用的连接 打电话,他们被适当标记。 当它们关闭时,它们就是 丢弃而不是返回 游泳池。