Esta semana descobrimos um erro muito grave ocorrendo no Paulovich.Data quando utilizamos o Context (Em alguns posts antigos era chamado de ApplicationContext). Basicamente o que implementamos foi uma solução simples para trabalhar com vários bancos de dados na aplicação utilizando o Design Partern IDisposable.

Dessa forma era possível alterar o banco de dados que seria afetado num diferente bloco de código, usando um simples using (new Context("nome da string")). Isso sempre funcionou em aplicações de menor porte, acho que durante mais de 6 meses já esta em produção sem maiores problemas.

Porém quando utilizamos este mesmo sistema multi-banco para um sistema 100 vezes maior, descobrimos um problema sutil, porém extremamente sério. Isso porque se formos analisar o código do Paulovich.Data na classe Context vamos encontrar o seguinte código:

public sealed class Context : IDisposable
{
public Context(string applicationAlias)
{
var app = Command.GetConnectionSettings(applicationAlias);
Command.SetConnection((DataBaseType)Command.GetDataBaseTypeByName(app.ProviderName), app.ConnectionString);
}

public void Dispose()
{
var settings = Command.GetDefaultConnectionSettings();
Command.SetConnection((DataBaseType)Command.GetDataBaseTypeByName(settings.ProviderName), settings.ConnectionString);
}
}

Ou seja, basicamente, chamamos dois métodos na Command que por sua vez, alteram o valor de uma variável estática que contém as informações de configuração da string de conexão.

private static ConnectionStringSettings commonConnectionStringSettings;

public static void SetConnection(string connectionString, string providerName)
{
commonConnectionStringSettings = new ConnectionStringSettings("dbPortal", connectionString, providerName);
}

Como você pode ver, é um funcionamento bem simples. Porém quando há muitos acessos, esta variável estática pode ser alterada antes do dispose(). Apontando para um Contexto diferente do que foi iniciado no using(new context()).

Após esta constatação. Sabíamos apenas que tinhamos um problemão. E depois de boas horas de pesquisa, nosso amigo e colega de trabalho, que também escreve aqui no 100loop, o Ricardo Cruz (Ricardão)… encontrou uma solução para garantir que esta variável não seja alterada por outros processos concorrentes. A solução foi adicionar um atributo na declaração da variável estática.

[ThreadStatic]private static ConnectionStringSettings commonConnectionStringSettings;;

Se você está utilizando o recurso de Context do Paulovich.Data, recomendamos que atualize seu assembly imediatamente.