C# 如何修复此代码中的SQL连接泄漏?

C# 如何修复此代码中的SQL连接泄漏?,c#,asp.net,.net,sql-server,ado.net,C#,Asp.net,.net,Sql Server,Ado.net,我在我的网站上发现此错误: 超时已过期。获取数据之前经过的超时时间 来自池的连接。发生这种情况的原因可能是所有的 连接正在使用,已达到最大池大小 描述:在执行过程中发生未处理的异常 当前的web请求。请查看堆栈跟踪以了解更多信息 有关错误的信息及其在代码中的来源 异常详细信息:System.InvalidOperationException:超时已过期。 从服务器获取连接之前经过的超时时间 水塘这可能是因为所有池连接都处于 已达到使用和最大池大小 这就是到处重复使用的C#类(我认为漏洞就在这里)

我在我的网站上发现此错误:

超时已过期。获取数据之前经过的超时时间 来自池的连接。发生这种情况的原因可能是所有的 连接正在使用,已达到最大池大小

描述:在执行过程中发生未处理的异常 当前的web请求。请查看堆栈跟踪以了解更多信息 有关错误的信息及其在代码中的来源

异常详细信息:System.InvalidOperationException:超时已过期。 从服务器获取连接之前经过的超时时间 水塘这可能是因为所有池连接都处于 已达到使用和最大池大小

这就是到处重复使用的C#类(我认为漏洞就在这里):

在我的方法中,我是这样使用的:

        var cmd = _generator.Connection.CreateCommand();
        cmd.CommandText = "SELECT * FROM SomeTable";
        var reader = cmd.ExecuteReader();

        while (reader.Read())
        {
            //DO SOMETHING
        }
        reader.Close();
private Generator _generator;

public HomeController()
{
    InitializeConnection();
}

private void InitializeConnection()
{
    _generator = new Generator();
}
编辑:在我的方法类中,我尝试在多个方法之间共享相同的SQL连接,如下所示:

        var cmd = _generator.Connection.CreateCommand();
        cmd.CommandText = "SELECT * FROM SomeTable";
        var reader = cmd.ExecuteReader();

        while (reader.Read())
        {
            //DO SOMETHING
        }
        reader.Close();
private Generator _generator;

public HomeController()
{
    InitializeConnection();
}

private void InitializeConnection()
{
    _generator = new Generator();
}

有人能看到我如何修复泄漏或导致我的最大池问题的原因吗?

您需要
使用
块来确保对象已被处置

using (var cmd = _generator.Connection.CreateCommand()) {
    cmd.CommandText = "SELECT * FROM SomeTable";
    using (var reader = cmd.ExecuteReader()) {

            while (reader.Read())
            {
                //DO SOMETHING
            }
    }
}

我也不会使用
连接
属性。最好根据需要打开和关闭连接,并允许连接池完成其工作。

连接没有关闭,只有读卡器关闭。您可以将与-一起使用,但如果使用ExecuteCommand,则没有此类有用的选项,您必须在连接对象上使用Close方法。

使用完连接后,您需要处理该连接

在您在问题中显示的代码中,我将执行以下操作:

  • 在释放生成器时,通过释放连接对象,使
    Generator
    实现
    IDisposable
  • 由于
    \u生成器
    看起来像一个字段,因此具有第二段代码的类可能还应该实现
    IDisposable
    并处理
    \u生成器
    内容

  • 另外,请注意,command对象还实现了
    IDisposable
    ,您应该始终处理实现您创建的
    IDisposable
    的对象。

    首先,生成器类拥有IDisposable对象(SqlConnection),因此应该实现IDisposable本身

    接下来,使用下划线前缀(
    \u generator.Connection.CreateCommand()
    )表明,\u generator可能是其他数据访问类的一个字段,因此需要自己实现IDisposable


    根据您发布的代码,您需要删除似乎没有任何用处的
    Generator
    类。

    由于您的Generator类不是静态的,因此每次创建Generator()对象时,您都会得到一个未关闭的新连接。你有几件事要做:

    • 将生成器类转换为Singleton模式,或将其完全删除
    • 让生成器实现IDisposable并调用cn.Dispose()
    • 确保每次调用Generator.Connection时都将其包装在using(…)块中

    不是c#开发人员,但不应该是
    this.cn
    或类似的,以表明cn是一个类变量,而不仅仅是连接方法中的局部变量?您不会在任何地方关闭连接。@MarcB-如果引用不含糊,无需使用
    this
    限定变量。我强烈建议将您的关闭(连接和读卡器取决于您最终如何组织它们)放在最后一个位置。如果抛出异常,您不希望泄漏连接。是否在每个页面中创建了_生成器?那么这就是你的泄漏源。你在这里关注的对象是错误的,虽然command对象实现了IDisposable,当然应该被处理掉,但他很可能没有处理存储在
    生成器
    实例中的连接,而将这些连接留给GC。@LasseV.Karlsen:是的,但他只有一个连接,除非他有多个
    \u生成器的实例。另外,我告诉他我不会使用
    连接
    属性。我正在尝试重用一个私有成员。我用如何初始化私人成员更新了我的问题。停止这样做。在重用连接方面,ADO.NET比您更聪明。只要在需要时创建并打开连接即可。