Заканчиваются соединения в пуле - PullRequest
2 голосов
/ 13 января 2012

У меня есть приложение для веб-форм, которое отображает список записей в GridView, и, установив несколько флажков, вы можете массово удалять записи.Сам код прост:

protected void btnDelete_Click(object sender, EventArgs e)
{
    int i = 0;
    try
    {
        foreach (GridViewRow row in GridView1.Rows)
        {
            CheckBox cb = (CheckBox)row.FindControl("ID");
            if (cb != null && cb.Checked)
            {
                int profileID = Convert.ToInt32(GridView1.DataKeys[row.RowIndex].Value);
                Profile profile = new Profile(profileID); //instantiate profile
                profile.Delete(); //call delete method
                i++;
            }
        }
        if (i > 0)
        {
            //report success to UI
        }
    }
    catch (Exception ex)
    {
        //report error to UI
    }
}

В конструкторе профиля он гидратирует объект, открывая соединение, открывая устройство чтения данных и затем устанавливая свойства объекта.Я тщательно описываю using() блоков в моем коде, поэтому каждое соединение с БД выглядит примерно так:

using (SQLHelper db = new SQLHelper())
{
    db.AddParameterToSQLCommand("@ProfileID", SqlDbType.Int);
    db.SetSQLCommandParameterValue("@ProfileID", id);

    using (SqlDataReader dr = db.GetReaderByCmd("up_GetProfile"))
    {
        if (dr.Read())
        {
            _profileID = id;
            if (!dr.IsDBNull(0))
                ProfileName = dr.GetString(0);
            //... and so on
            return true;
        }
        else
        {
            return false;
        }
    }
}

В устройстве чтения данных реализован iDisposible, как и мой вспомогательный класс, а деструктор выглядит так:

public void Dispose()
{
    try
    {
        //Clean Up Connection Object
        if (mobj_SqlConnection != null)
        {
            if (mobj_SqlConnection.State != ConnectionState.Closed)
            {
                mobj_SqlConnection.Close();
            }
            mobj_SqlConnection.Dispose();
        }

        //Clean Up Command Object
        if (mobj_SqlCommand != null)
        {
            mobj_SqlCommand.Dispose();
        }
    }

    catch (Exception ex)
    {
        throw new Exception("Error disposing data class." + Environment.NewLine + ex.Message);
    }
}

Когда я перебираю свой код, я вижу, что соединения всегда открываются и закрываются правильно, мой стек никогда не превышает пяти или шести вызовов (у меня нет проблем с рекурсией). Я подтвердил, чтовесь мой код доступа к данным правильно упакован с использованием блоков, но мои соединения не возвращаются обратно в пул.Вместо этого я получаю эту ошибку:

Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.

Это происходит в выделенном пуле приложений, когда один пользователь выполняет удаление из 10+ профилей.Это кажется , как будто я все делаю правильно, но я не знаю, почему соединения не освобождаются обратно в пул.На большинстве должно быть когда-либо только два соединения, открытых исполняющим потоком, оба из которых должны (и делают!) Удаляться, когда они выходят из области видимости.

Я явно что-то делаю не так, но не могу понять, что за жизнь.

Ответы [ 2 ]

4 голосов
/ 13 января 2012

Из моего комментария я преобразую в ответ.

Похоже, вы пытаетесь закрыть объекты Connection перед объектами Command, а поскольку объекты Command ссылаются на соединение, возможно, он сохраняетсоединение живое.

Попробуйте переключить их:

//Clean Up Command Object
if (mobj_SqlCommand != null)
{
  mobj_SqlCommand.Dispose();
}

if (mobj_SqlConnection != null)
{
  if (mobj_SqlConnection.State != ConnectionState.Closed)
  {
    mobj_SqlConnection.Close();
  }
  mobj_SqlConnection.Dispose();
}
1 голос
/ 13 января 2012

Если я правильно помню, утилита SqlHelper не закрывает соединение автоматически. Вам нужно явно закрыть его.

Мы всегда переносим использование SqlHelper в try / finally и явно вызываем close в finally.

...