【问题标题】:Timeout expired. The timeout period elapsed prior to obtaining a connection First connection超时已过。获得连接前的超时时间 第一个连接
【发布时间】:2013-02-26 07:34:28
【问题描述】:

我有这个问题。我用谷歌搜索了很多关于这个问题的网站,但他们都建议关闭所有连接,或者只是使用连接和 dataReader 的“使用”。但!我的问题在于我无法打开第一个连接!我在连接附近设置了一个断点,并看到没有其他连接,所以,有第一个。当我重新制作从静态到单例的打开连接的类时,这个问题就出现了,这里是代码:

public class Storage
{
private static Storage instance;

public static Storage Instance
{
    get
    {
        if (instance == null)
        {
            instance = new Storage();
        }
        return instance;
    }
}

private Storage()
{
    Manager man = new Manager();
    products = man.LoadProducts();
    components = man.LoadComponents();
    man.LoadProductComponents();
}

public Dictionary<int, Product> Products
    {
        get { return products; }
        set { products = value; }
    }

public Dictionary<int, Component> Components
    {
        get { return components; }
        set { components = value; }
    }

private Dictionary<int, Product> products;
private Dictionary<int, Component> components;

}

这是一个Manager构造函数

    public Manager()
    {
        connection = new SqlConnection(@"Persist Security Info=False;User ID=user;Password=pass;Initial Catalog=Products;Server=(local)");
        if (connection.State != ConnectionState.Open) connection.Open();
    }

当异常引发时,连接为Closed。有人有想法吗?

更新:

如果我关闭池 - 我在同一行有 "System.StackOverflowException" in System.Data.dll

【问题讨论】:

  • 就我个人而言,任何涉及固定在单例中的连接本质上都是一个坏主意。但是:还有多少其他地方可以使用负载管理器?特别是,任何引起少数经理人注意的事情都会产生锁定连接而没有希望关闭它们的副作用。
  • 问题出在第一次连接上,所以 Manager() 合二为一。我尝试使用 lock() 制作单例,但没有帮助。
  • 这是整个应用程序中唯一的连接/管理器实例吗?消息是否以“from the pool”结尾?
  • @MarcGravell 超时已过期。在从池中获取连接之前超时时间已过。这可能是因为所有池连接都在使用中并且已达到最大池大小。
  • 如果我将 Manager 和 Storage 设为静态 - 一切正常。

标签: c# sql-server design-patterns connection-pooling


【解决方案1】:

您的Manager 类创建并打开一个连接:

public Manager()
{
    connection = new SqlConnection(@"Persist Security Info=False;User ID=user;Password=pass;Initial Catalog=Products;Server=(local)");
    if (connection.State != ConnectionState.Open) connection.Open();
}

但是,如果我们看看您是如何使用它的,很明显没有任何东西关闭这个连接:

private Storage()
{
    Manager man = new Manager();
    products = man.LoadProducts();
    components = man.LoadComponents();
    man.LoadProductComponents();
}

我希望Manager 实现IDisposable,并让Dispose() 方法关闭并释放连接:

class Manager : IDisposable
{
    ...
    public void Dispose()
    {
        if(connection != null) connection.Dispose();
        connection = null;
    }
}

然后将通过 using:

使用
private Storage()
{
    using(Manager man = new Manager())
    {
        products = man.LoadProducts();
        components = man.LoadComponents();
        man.LoadProductComponents();
    }
}

我担心的是,你的经理只是一个更广泛问题的一个例子:你自己没有清理连接。当Manager 是静态的时,这可能是不可见的,但是当切换到Manager 实例时,很容易旋转多个Manager 对象。这些中的每一个都会在 GC 之前建立一个连接。

【讨论】:

  • 我说,我可以看到,当出现异常时,连接状态为关闭。那么,您的 Dispose() 如何帮助我?是第一次连接,就是第一次连接不上。
  • @user1947702 如何放置这个...第一次连接不会出现特定的错误消息。当您通过不清理连接而使池饱和时会发生这种情况。而且您发布的代码不会清理连接。我非常怀疑是否有其他连接正在创建,可能在代码的其他地方,这会使池饱和。
猜你喜欢
  • 2014-07-07
  • 2015-09-15
  • 1970-01-01
  • 1970-01-01
  • 2014-01-29
  • 1970-01-01
  • 2017-02-20
  • 2014-03-17
  • 1970-01-01
相关资源
最近更新 更多