代码之家  ›  专栏  ›  技术社区  ›  Paul Hollingsworth

.NET sqlconnection类、连接池和重新连接逻辑

  •  8
  • Paul Hollingsworth  · 技术社区  · 16 年前

    我们有一些客户端代码使用.NET中的sqlconnection类与sqlserver数据库通信。由于此错误,它间歇性失败:

    “ExecuteReader需要打开的可用连接。连接的当前状态为“关闭”

    “临时”的解决方案是重新启动流程,然后一切都正常工作——但是,这显然是不令人满意的。

    代码保存一个sqlconnection实例的缓存,每个数据库一个。

    我们想重新编写代码,但在编写代码之前,我需要知道一些事情:

    我的第一个问题是:重复连接和断开sqlconnection对象是否效率低下,或者底层库是否代表我们执行连接池?

    // Is this bad/inefficient?
    for(many-times)
    {
        using(SQLConnection conn = new SQLConnection(connectionString))
        {
            // do stuff with conn
        }
    }
    

    因为我们的代码 执行上述操作,问题的可能原因似乎是,在连接的“生存期”期间,底层SQLServer数据库发生了导致连接关闭的事件…

    如果事实证明“缓存”sqlconnection对象是值得的,那么建议使用什么方法来处理可以通过“重新连接”到数据库来解决的所有错误。我说的是一些场景,比如:

    • 数据库脱机并重新联机,但在发生这种情况时,客户端进程没有打开的事务。
    • 数据库被“断开”,然后“重新连接”

    我注意到在sqlconnection上有一个“state”属性…有没有合适的方法来查询?

    最后,我设置了一个具有完全访问权限的测试SQLServer实例:如何复制准确的错误“ExecuteReader需要一个开放的可用连接”。连接的当前状态为“关闭”

    3 回复  |  直到 9 年前
        1
  •  20
  •   Jon Skeet    16 年前

    不,创造大量的 SqlConnection 对象,完成后关闭每个对象。这正是该做的事。让.NET框架连接池完成它的工作-不要自己尝试。您不需要执行任何特定的操作来启用连接池(尽管您可以通过设置 Pooling=false 在连接字符串中)。

    如果您尝试自己缓存连接,有很多事情可能会出错。只说不:

        2
  •  2
  •   Remus Rusanu    16 年前

    您应该启用 connection pooling 在连接字符串上。在这种情况下,运行时会在关闭“池”时将连接添加回“池”,而不是真正断开连接。当从池中取出一个“新”连接时,它将被重置(即调用sp_reset_connection),然后作为一个全新的新连接呈现给您的应用程序。池可以透明地处理这些情况,就像在池中空闲时连接被关闭一样。

    “从头开始”创建新连接的成本很高,因为身份验证需要在客户端和服务器之间进行多次往返(取决于身份验证方法和SSL设置,在最佳情况下可以是1次往返,而在较差情况下可以是10次往返)。

    为了回答你的问题,联系提出 OnStateChange 当它们的状态发生变化时发生事件,但如果使用池,则不应该关心这一点。

        3
  •  1
  •   Paul    13 年前

    根据我最近的经验,如果您使用此代码:

    using(SQLConnection conn = new SQLConnection(connectionString))
    {
        // do stuff with conn
    }
    

    出现错误,并且不显式关闭连接,它将不会关闭或签回池中。所以使用catch或finally块关闭连接