代码之家  ›  专栏  ›  技术社区  ›  Robert Wagner

检测数据库连接出错

  •  1
  • Robert Wagner  · 技术社区  · 17 年前

    作为单元测试的一部分,我们在测试开始时还原一个空白数据库。然后,单元测试通过调用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服务器也可以实现同样的效果。

    我们面临的问题是,Web服务不知道连接何时被终止,只是从连接池中选择了一个“坏”的连接。此外,在应用程序中,连接的创建和命令的执行是分开的几层。

    我们如何在执行命令之前检测到连接“坏”,而不会严重影响应用程序的性能?

    2 回复  |  直到 17 年前
        1
  •  2
  •   to StackOverflow    17 年前

    终止SQL Server后,您的连接池将包含到SQL Server旧实例的过时连接。

    您可以调用SqlConnection。ClearAllPools()用于在重新启动SQL Server后从池中清除过时的连接,例如:

    static void Main(string[] args)
    {    
        DoDBStuff();    
        new Server("localhost").KillAllProcesses("Test");
        SqlConnection.ClearAllPools();
        DoDBStuff();
    }
    

    NB中介绍了ClearAllPools方法。NET 2.0

        2
  •  1
  •   SqlRyan    17 年前

    出于单元测试的目的,您可以调整连接池超时吗?这样,连接会更快地过时,它们会在您的签出/编译过程中过期,并在实际单元测试运行时全部清除?

    或者,作为另一种选择,您可以编写一个首先执行的单元测试,并调用一个刷新现有连接池的Web服务吗?它将强制任何新的数据请求生成一个新的DB连接,这不会导致异常。根据MSDN:

    阿多。NET 2.0引入了两种新方法 清理游泳池:ClearAllPools和 ClearPool。ClearAllPools清除 给定提供商的连接池, ClearPool清除连接 与关联的池 具体连接。如果有 当时正在使用的连接 呼叫时,它们会被适当标记。 当它们关闭时,它们 丢弃而不是归还 游泳池。