Reutilizando a conexão no LINQ To SQL


Uma das boas práticas que sempre foram pregadas ao escrever código de acesso à dados é abrir a conexão o mais tarde e fechar o mais cedo possível. Isso deve-se ao fato de que acessar algum recurso deste tipo é uma tarefa custosa e, caso não seja dada a devida atenção, podemos ter alguns problemas relacionados a performance.

Há alguns cenários onde essa técnica sofre uma pequena variação. Um exemplo é quando há várias queries a serem executadas e, se a cada uma delas abrirmos e fecharmos a conexão, isso irá piorar consideravelmente. Neste caso, é nítida a necessidade da reutilização de uma mesma conexão para efetuar os comandos. Ainda abriremos o mais tarde e fecharemos o mais cedo possível, mas aumentando o intervalo de tempo entre essas duas ações.

Quando trabalhamos com o LINQ To SQL, temos uma classe derivada de DataContext que encapsula o acesso os dados. A cada execução, essa classe abrirá a conexão, executará o comando desejado e, em seguida, fechará a conexão com o respectivo banco de dados. Utilizando o DataContext envolvido ou não em um bloco using, ele sempre executará estes passos para cada uma das queries executadas a partir dele, ou seja, é o comportamento padrão.

Assim como já era fornecido pela classe SqlDataAdapter, há uma versão do construtor da classe DataContext que possibilita fornecer uma conexão já aberta para que ele utilize-a por todas as queries. Basicamente o que ele faz é identificar se a instancia da conexão que é passada como parametro para a DataContext já está aberta; caso esteja, depois de executar a query, ela não será fechará, nos obrigando a fechá-la explicitamente. Se analisarmos os internals da classe DataContext, veremos que existe uma classe não documentada chamada SqlConnectionManager que é responsável por essa manipulação.

Em alguns testes, podemos notar a diferença entre os dois modos de acesso, ou seja, aquele convencional, onde cada comando abre e fecha a conexão, e o segundo modo que reutiliza a mesma conexão para todos os comandos. No primeiro caso, temos os seguintes resultados:

[ Modo Convencional ]
using (DataClasses1DataContext ctx =
    new DataClasses1DataContext(“CONNECTION_STRING”))
{
    //executar várias queries
}

    01: 00:00:01.3890421
    02: 00:00:00.9600488
    03: 00:00:00.9668471
    04: 00:00:01.0287346
    05: 00:00:00.9587953
    06: 00:00:01.1188069
    07: 00:00:01.0369689
    08: 00:00:01.0047073
    09: 00:00:00.9850514
    10: 00:00:00.9772066

Utilizando a segunda opção, devemos criar a conexão com o banco de dados e abrí-la explicitamente antes de passá-la para o construtor da classe DataContext. É importante lembrar que neste caso, a conexão não será fechada implicitamente. Dependendo da frequencia de utilização desta técnica, a criação deste código poderá ser repetitiva. Para encapsular todo esse trabalho, criei uma classe chamada ConnectedDataContext<TDataContext>. Abaixo consta a sua definição:

public class ConnectedDataContext<TDataContext> : IDisposable where TDataContext : DataContext
{
    //implementação
}

[ Reutilizando uma mesma conexão ]
using (ConnectedDataContext<DataClasses1DataContext> ctx =
                new ConnectedDataContext<DataClasses1DataContext>(“CONNECTION_STRING”))
{
    //executar várias queries
}

    01: 00:00:01.0577727
    02: 00:00:00.7618577
    03: 00:00:00.6605342
    04: 00:00:00.6552123
    05: 00:00:00.6637952
    06: 00:00:00.6604886
    07: 00:00:00.6363001
    08: 00:00:00.6754408
    09: 00:00:00.7525822
    10: 00:00:00.6538641

Publicidade

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s