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