Пул подключений с внедрением зависимостей Использовать область запросов HTTP или нет? - PullRequest
2 голосов
/ 10 марта 2012

Примечание: Я не планирую использовать Entity Framework, поскольку он НЕ поддерживает асинхронные запросы.

Я не могу понять, какой подход будет лучше для следующего сценария с внедрением зависимостей и пулами соединений SQL. Пул подключений к SQL Server (ADO.NET) В статье MSDN рекомендуется использовать using (sqlConn), поскольку я не обращаю внимание на connection.Open() и connection.Close() при включенном пуле подключений.

Техника 1:

  • Внедрить зависимость SqlConnection в мой класс CustomerRepository.
  • Использовать экземпляр для каждого HTTP-запроса для SqlConnection.
  • Позвоните connection.Open(), прежде чем он будет введен в класс CustomerRepository.

Техника 2:

  • Внедрить только строку подключения в мой CustomerRepository класс.
  • Инициализировать using (SqlConnection) блоков в каждом из моих методов CRUD?

Дополнительные моменты, которые следует учитывать

  1. Я буду использовать асинхронные вызовы с моим SqlCommand.BeginExecuteReader() для некоторых запросов SQL, выполнение которых занимает около 2-4 секунд.
  2. В некоторых особых сценариях мне также нужно запускать 2 или более параллельных вызова SQL-запроса.
  3. Пожалуйста, имейте в виду, как эти две техники влияют на стиль кодирования для IDisposable и using (connection).

Вопросы

  1. Существуют ли различия между двумя подходами , учитывая, что Пул соединений включен ?
  2. Какую технику мне использовать и почему?

Пример кода для техники 1:

// ------------------------------------------------------------
// Autofac Dependency Injection setup
// ------------------------------------------------------------
ContainerBuilder builder = new ContainerBuilder();
builder.Register(
    c => {
        var conn = new SqlConnection( "connectionString" );
        conn.Open(); // open the connection ahead of time before injecting it into my CustomerRepository
        return conn;
    })
    .Named("myNamedConnection", typeof(SqlConnection))
    .InstancePerHttpRequest();


builder.Register(
    c => {
        new CustomerRepository(c.ResolveNamed<SqlConnection>("myNamedConnection")))
    })
    .As<ICustomerRepository>();



// ------------------------------------------------------------
// CustomerRepository
// ------------------------------------------------------------
public class CustomerRepository : ICustomerRepository, IDisposable
{
    private SqlConnection conn;
    private bool disposed;
    public CustomerRepository(SqlConnection connection)
    {
        conn = connection;
        disposed = false;
    }

    public Customer GetById(int id)
    {
        using (var cmd = conn.CreateCommand())
        {
            // code to retrieve Customer by id
        }
    }


    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                if (conn != null)
                {
                    conn.Dispose();
                    conn = null;
                }
            }

            disposed = true;
        }
    }
}

Пример кода для техники 2:

// ------------------------------------------------------------
// CustomerRepository
// ------------------------------------------------------------
public class CustomerRepository : ICustomerRepository
{
    private readonly string strConn;
    public CustomerRepository(string strConnection) // strConnection has Connection Pooling enabled
    {
        strConn = strConnection;
    }

    public Customer GetById(int id)
    {
        using (var conn = new SqlConnection(this.strConn))
        {
            using (var cmd = conn.CreateCommand())
            {
                // code to retrieve Customer by id
            }
        }
    }
}

Заранее благодарим за любые вдумчивые замечания: -)

1 Ответ

1 голос
/ 10 марта 2012

Не используйте технику 1. Не рекомендуется оставлять соединение открытым для полного запроса: его следует закрыть как можно скорее, поэтому не оставляйте его открытым для полного запроса.

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

Возможно, вам лучше добавить некую абстракцию IDatabase в свои репозитории.Вы можете добавить строку подключения в вашу IDatabase реализацию.Эта абстракция может иметь метод BeginExecuteReader или, возможно, даже некоторую абстракцию более высокого уровня.

...