Используя оператор C # 'using' с функцией пользовательского объекта, мне нужно реализовать IDisposable? - PullRequest
8 голосов
/ 27 мая 2009

У меня есть класс диспетчера sqlConnection:

public class SQLConn {
  public string connStr = System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"];

  private SqlConnection sqlConn;

  public SqlConnection Connection()
  {
      sqlConn = new SqlConnection(connStr);

      return sqlConn;
  }

  public void Open()
  {
        sqlConn .Open();
  }
}

Если я использую функцию с оператором using, например:

var conn = new SQLConn();

using (conn.Connection()) 
{ 
    String query = "Select * from table";
    objSql = new SqlCommand(query, conn.Connection());      

    conn.Open(); 
    DoSomething(); 
}

Оператор using удаляет соединение автоматически, поскольку conn.Connection() возвращает объект SqlConnection? Или я должен реализовать IDisposable и пользовательский метод Dispose для класса SqlConn?

Это вообще хороший способ? Я работаю с устаревшим кодом и пока не могу использовать ORM, но есть ли способ упростить этот существующий шаблон для управления / создания соединений SQL?

Ответы [ 8 ]

12 голосов
/ 27 мая 2009

Оператор using будет искать окончательный тип выражения - то есть все, что возвращается из .Connection(); если это возвращает что-то, что IDisposable, то вы в порядке.

Компилятор сообщит вам, если вы ошиблись ;-p (он не позволит вам использовать using для чего-то, что не IDisposable).

Вы, вероятно, должны следить за тем, где вы создаете два соединения:

using (var c = conn.Connection()) // <==edit
{ 
    String query = "Select * from table";
    objSql = new SqlCommand(query, c); // <==edit

    c.Open(); 
    DoSomething(); 
}

и, возможно:

public SqlConnection Connection()
{
  if(sqlConn == null) sqlConn = new SqlConnection(connStr); // <== edit
  return sqlConn;
}
5 голосов
/ 27 мая 2009

Это будет работать, но после using {} у вас останется sqlConn, который внутренне содержит Disposed SqlConnection. Не очень полезная ситуация

1 голос
/ 28 февраля 2012

Чтобы прояснить сказанное выше:

Любой объект, который вам нужно использовать с использованием, должен быть расположен в конце инструкции использования. Таким образом, компилятору необходимо убедиться, что ваш тип реализует интерфейс IDisposable, когда он видит использование этого объекта типа, или он не отпустит вас.

1 голос
/ 27 мая 2009

, чтобы ответить на вопрос заголовка, вы должны реализовать IDisposable в классе, объект которого вы используете с помощью «using». В противном случае вы получите ошибку во время компиляции.

Тогда, да, «использование» избавит вас от SqlConnection в конце блока. Думайте об «использовании» как о «try-finally»: в блоке «finally» существует неявный вызов Dispose ().

Наконец, более чистый код будет:

using( SqlConnection = new SqlConnection( connStr ) {
    // do something
}

По крайней мере читателям вашего кода не придется прилагать умственных усилий, чтобы понять, как Хенк Холтерман указал, что ваш объект SQLConn содержит ссылку на удаленное соединение.

1 голос
/ 27 мая 2009

Ваш код неверен!

Должно быть что-то вроде этого:

Dim conn as New SQLConn();
Dim sqlConnection New SQLConnection();

sqlConnection = conn.Connection();

using (sqlConnection) 
{ 
    String query = "Select * from table";
    objSql = new SqlCommand(query, sqlConnection);      

    conn.Open(); 
    DoSomething(); 
}

Таким образом, оператор using удалит соединение в конце.

0 голосов
/ 27 мая 2009

Кажется, что соединение будет закрыто должным образом, но это не рекомендуется:

Вы можете создать экземпляр ресурса объект, а затем передать переменную оператор использования, но это не лучшая практика В этом случае объект остается в области видимости после контроля покидает блок использования, даже если он вероятно, больше не будет иметь доступа к его неуправляемые ресурсы. В других словами, больше не будет инициализируется. Если вы попытаетесь использовать объект за пределами использования блока, вы риск возникновения исключения выброшены. По этой причине это как правило, лучше создать экземпляр объект в выражении использования и ограничить его область применения блоком.

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

0 голосов
/ 27 мая 2009

С MSDN :

Объект, предоставленный для использования заявление должно реализовывать IDisposable интерфейс.

Вы не должны вызывать Dispose (), однако, оператор using неявно делает это за вас.

0 голосов
/ 27 мая 2009

Нет, пока вы возвращаете объект IDisposable.

Возвращенный объект не должен реализовывать IDisposable, но тогда блок using не будет иметь смысла.

...