Утилизация устройства чтения данных при его построении по значению по сравнению со ссылкой - PullRequest
2 голосов
/ 02 июля 2011

Вопрос новичка о том, когда действительно читатель выпускается, когда он построен в классе, используя ref против var.Я тестировал это сегодня, и результаты меня немного озадачивают - в надежде разобраться в этом.

У меня есть класс, который я использую для извлечения данных через ODBC с многочисленных удаленных серверов, но мне нужночтобы ограничить количество соединений ODBC, открытых для каждого сервера, к которому я подключен, - поэтому я стараюсь правильно распределять устройства чтения данных, когда я закончу с ними, прежде чем открывать другой.Короткая версия: у меня есть метод с именем FillDataReader, который принимает объект для чтения данных, заполняет его на основе вашего запроса и передает его обратно.

Если я передаю его с помощью ref и удаляю устройство чтения данных извызывающая сторона, все хорошо.Соединение сбрасывается немедленно, и клиентская сторона может заполнить другой считыватель данных, не сжигая соединение.Однако, если я передам по значению, ресурс не будет освобожден, и если я открою другое устройство чтения данных со стороны клиента, у меня теперь будет два соединения с этим сервером.

Концептуально я понимаю разницу - с ref используется только один адрес, так как он передает «указатель на указатель», и утилизация освобождает этот ресурс.Хорошо, но даже если передать по значению и сделать явное распоряжение на стороне клиента, что именно удерживает ресурс?Я предпочел бы передать здесь значение, чтобы я мог использовать изящную конструкцию using на стороне клиента, но что более важно, я хочу лучше понять, что здесь происходит.Вкратце, вот как это выглядит

[класс извлечения БД]

public bool FillDataReader(string pQueryString, ref System.Data.Odbc.OdbcDataReader pDataReader, out string pErrorReason)
        {
(uses a connection object that’s been established at class construction time and stays up all the time)
...
            try
            {
                pDataReader = _Command.ExecuteReader();
            }
...
         }

[Calling class]

strSQL = "SELECT Alias, ObjectID, FROM vw_GlobalUser";
               if (ServerList[currentServer].DatabaseFunctions.FillDataReader(strSQL, ref drTemp, false, out strErrorReason) == false)
               ….

    drTemp.Dispose();

(at this point the connection is released to the server)

Однако, если я уберу ref в точке Dispose в вызывающем классе, соединение не будетвышел.Это уходит в конце концов, но мне нужно, чтобы это ушло немедленно (отсюда и призыв избавиться).

Значит, функция заполнения в классе извлечения DB висит на ссылке на выделенное пространство в куче?Я не уверен, что понимаю, почему это так - понял, что он использует другую копию адреса для чтения данных в стеке для ссылки на объект чтения данных в куче, но когда он выходит из области видимости, разве это не освобождается?Может быть, мне нужно больше кофе ...

1 Ответ

0 голосов
/ 02 июля 2011

Поскольку ваш вызывающий код должен получить ссылку для освобождения объекта, вам нужно ref (или out). В противном случае параметр передается только методу, но не обратно, поэтому drTemp не обновляется средством чтения данных, созданным в методе FillDataReader.

Обратите внимание, что вы можете изменить подпись следующим образом, чтобы прояснить намерение:

public Result TryGetDataReader(string pQueryString, out System.Data.Odbc.OdbcDataReader pDataReader)

Изменения, которые я предлагаю:

  • Введено соглашение об именах с "Try", которое является общим для этого типа метода
  • Сделал pDataReader out, так как его не нужно инициализировать при вызове метода
  • Введен тип «Результат», который должен содержать информацию об успехе и сообщение об ошибке (если есть)
...