检测到数据库连接出错

时间:2008-12-02 03:32:56

标签: .net ado.net

作为单元测试的一部分,我们在测试开始时恢复空白数据库。然后,单元测试通过调用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不知道什么时候连接被杀死,只是从连接池中选择“坏”连接。此外,连接的创建和命令的执行在应用程序中分开了几层。

如何在执行命令之前检测到连接是“坏”,而不会对应用程序的性能产生很大影响?

2 个答案:

答案 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关联的池   具体连接。如果有   在使用时使用的连接   打电话,他们被适当标记。   当它们关闭时,它们就是   丢弃而不是返回   游泳池。