Какой лучше утилизировать объект? - PullRequest
0 голосов
/ 26 сентября 2018

В случае этого метода:

public void Delete(int id)
{
    using (var connection = GetOpenConnection())
    {
        connection.Execute($"DELETE FROM MyTable WHERE Id = {id}");
    }
}

Или просто:

GetOpenConnection().Execute($"DELETE FROM MyTable WHERE Id = {id}");

Интересно, является ли второй вариант лучшим для упрощения обслуживания и упрощения.

Ответы [ 3 ]

0 голосов
/ 26 сентября 2018

Ответ на этот вопрос требует понимания того, как Sql Server (и другие базы данных) используют соединения, и как ADO.Net использует пул соединений.

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

.Net решает эту ситуацию двумя способами.Во-первых, библиотека ADO.Net, которую вы используете для доступа к базе данных (System.Data и компания), включает в себя функцию под названием Пул соединений .Эта функция объединяет и кэширует соединения для вас, чтобы эффективно открывать и закрывать соединения по мере необходимости.Эта функция означает , что вы не должны пытаться поддерживать общий объект соединения активным на протяжении всего жизненного цикла приложения или сеанса. Позвольте пулу соединений справиться с этим и создайте новый объект соединения для большинства поездок в базу данных.

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

Другими словами, блок using в первом примеревыполняет важную функцию .Это ошибка - пропускать это.В загруженной системе это может даже привести к ситуации отказа в обслуживании вашей базы данных.

Вы понимаете это в самом заголовке вопроса, который спрашивает: «Какой объект лучше утилизировать?»Только один из этих двух образцов избавляется от объекта вообще.

0 голосов
/ 26 сентября 2018

Вы можете подходить к дизайну таким образом.

using(var context = new CustomerFactory().Create())
     return context.RetrieveAll();

Тогда внутри вашего CustomerContext у вас будет логика удаления, соединение с базой данных и ваш запрос.Но вы можете создать наследовать класс DbConnectionManager, который будет иметь дело с соединением.Но весь класс будет удален, что также спасло бы диспетчер соединений.

public interface ICustomerRepository : IDisposable
{
     IEnumerable<Customer> RetrieveAll();
}

public interface ICustomerFactory
{
     ICustomerRepository Create();
}

public class CustomerFactory : ICustomerFactory
{
     public ICustomerRepository Create() => new CustomerContext();
}

public class CustomerContext : ICustomerRepository
{
     public CustomerContext()
     {
          // Instantiate your connection manager here.
     }

     public IEnumerable<Customer> RetrieveAll() => dbConnection.Query<Customer>(...);
}

Это было бы, если вы хотите заглушить выразительный вызов, что-то вроде представления вашего гибкого синтаксиса во втором варианте, безнегативное воздействие.

0 голосов
/ 26 сентября 2018

Первая опция обеспечивает предсказуемость: объект соединения, возвращенный из GetOpenConnection(), будет удален, как только connection.Execute завершится.

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

Поэтому следует предпочесть первый подход.

Примечание: Рассмотрите возможность параметризации вашего запроса.Даже если в вашей ситуации вставка id в запрос не представляет угрозы, поскольку тип id имеет тип int, рекомендуется последовательно использовать параметры в коде.

...