У меня есть класс под названием DatabaseHelper, который обертывает DbConnection. Каков правильный способ установки этого класса для использования оператора? Я реализовал IDisposible, но я не уверен, когда и где я должен звонить Connection.Close() или Connection.Dispose().
Когда я просто вызываю Connection.Dispose() в моем собственном методе Dispose(), иногда я получаю SocketException из моего объекта DbConnection. Я предполагаю, что это связано с тем, что старые подключения остаются открытыми, но никаких подробностей не привязаны к исключению, поэтому я не знаю точно.
Вызовите соединение. Задайте() из вашего метода dispose. Вы должны посмотреть на стандартный шаблон для реализации IDisposable, который выходит за рамки простого внедрения интерфейса IDisposable и позволяет удалять неуправляемые объекты и т.д.:
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Dispose managed resources.
}
// There are no unmanaged resources to release, but
// if we add them, they need to be released here.
}
disposed = true;
// If it is available, make the call to the
// base class Dispose(Boolean) method
base.Dispose(disposing);
}
(взято из http://msdn.microsoft.com/en-us/library/system.idisposable.aspx).
Согласно эта группа новостей:
Вот как реализуется IDbConnection.Dispose() (как показывает утилита Reflector):
SqlClient:
protected override void Dispose(bool disposing)
{
if (disposing)
{
switch (this._objectState)
{
case ConnectionState.Open:
{
this.Close();
break;
}
}
this._constr = null;
}
base.Dispose(disposing);
}
Odbc:
protected override void Dispose(bool disposing)
{
if (disposing)
{
this._constr = null;
this.Close();
CNativeBuffer buffer1 = this._buffer;
if (buffer1 != null)
{
buffer1.Dispose();
this._buffer = null;
}
}
base.Dispose(disposing);
}
OleDb:
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (this.objectState != 0)
{
this.DisposeManaged();
if (base.DesignMode)
{
OleDbConnection.ReleaseObjectPool();
}
this.OnStateChange(ConnectionState.Open, ConnectionState.Closed);
}
if (this.propertyIDSet != null)
{
this.propertyIDSet.Dispose();
this.propertyIDSet = null;
}
this._constr = null;
}
base.Dispose(disposing);
}
Ваш метод dispose должен только пытаться закрыть соединение, если он открыт.
Этот синтаксис деструктора является актуальным для финализатора. Финализатор вызывает Dispose (false) Метод.
#region IDisposable Members
private bool _isDisposed;
private void ThrowIfDisposed()
{
if (_isDisposed)
throw new ObjectDisposedException(this.GetType().Name);
}
protected virtual void Dispose(bool disposing)
{
if (!_isDisposed)
{
if (disposing)
{
//part 1 : disposing managed objects
_command.Dispose();
_command.Connection.Dispose();
if (_command.Transaction != null)
_command.Transaction.Dispose();
}
//part 2: disposing unmanged objects. Here there are no unmanged objects.
_isDisposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
//~DbCommandExecutor() //No need of finalize here. Because there is no unmanged objects in my class. ie, no code in part 2.
//{
// Dispose(false);
//}
#endregion
не требуется синтаксиса финализатора (или деструктора) , пока ваш код не будет иметь код части 2. В противном случае он должен быть реализован для безопасной стороны. т.е. даже если программист не вызывает метод удаления правильно, финализация должна очистить неуправляемые ресурсы.
сравните примеры: из msdn
http://msdn.microsoft.com/en-us/library/system.idisposable.dispose.aspx и http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx
Чтобы закончить шаблон реализации IDisposable, он включает в себя финализатор (деструктор) для вашего класса, который вызывает метод Dispose() (передает false). Это действует как отказоустойчивый механизм, позволяющий избавиться от неуправляемых объектов, если потребитель класса не вызвал Dispose().
~MyClass()
{
Dispose(false);
}