Como liberar conexões fantasmas (inativas) do SQL Server 2005?

Como liberar conexões fantasmas (inativas) do SQL Server 2005?

Neste artigo não irei me aprofundar em explicação de conceitos de SQL, mas somente compartilhar uma solução para o problema que tive. Qualquer dúvida favor postar um comentário que eu respondo.

Há alguns dias atrás estava com um problema relacionado com pool de conexões no SQL Server. O cenário era uma aplicação web em asp.net que abria conexões e fechava normalmente porém por algum problema de comunicação entre o servidor de banco de dados e o de aplicação acarretava em conexões inativas no gerenciador de processos do SQL Server. Investigando possíveis situações que poderiam ocasionar este problema, encontrei um artigo que dizia que em alguns casos o gerenciador do SQL deixa conexão no pool se tiver algum problema de comunicação com cliente.

Após saber disto encontrei um artigo falando sobre as duas Stored Procedures que lista informações de processos que são:
- sp_who lista processos com informações básicas;
- sp_who2 lista processos com informações detalhadas;

Porém eu precisava acrescentar algumas condições, como: pegar somente conexões com status “sleeping”, de um usuário e que não tivesse nenhuma transação aberta. Sendo assim, fiz mais uma pesquisa para saber qual era a tabela que continha essas informações e então encontrei a SYS.SYSPROCESSES localizada no Banco de dados Master, por último faltava saber o comando que exclui processo e então o encontrei KILL.

Com todas as informações montei então o seguinte script para rodar na base de dados Master:

DECLARE @KILLSPIDPREZA VARCHAR(30)

DECLARE KILL_PROC_PREZA CURSOR FOR
SELECT 'KILL '+CAST(SPID AS VARCHAR) FROM SYS.SYSPROCESSES
WHERE STATUS='SLEEPING' AND LOGINAME='Nome_desejado' AND OPEN_TRAN=0

OPEN KILL_PROC_PREZA
FETCH NEXT FROM KILL_PROC_PREZA INTO @KILLSPIDPREZA
WHILE @@FETCH_STATUS = 0
 BEGIN
   EXECUTE (@KILLSPIDPREZA)
   FETCH NEXT FROM KILL_PROC_PREZA INTO @KILLSPIDPREZA
 END
CLOSE KILL_PROC_PREZA
DEALLOCATE KILL_PROC_PREZA

Crei um job no sqlServer para executar o script de 1 em 1 minuto e não tive mais problemas com conexões preza.
Lembrando que essa solução talvez não seja a melhor, mas para o momento foi a mais eficiente que encontrei para solucionar o problema em curto prazo.

Referências:
http://support.microsoft.com/kb/137983/pt-br (Conexões orfãos)
http://msdn.microsoft.com/en-us/library/ms173730.aspx (Comando KILL)
http://msdn.microsoft.com/en-us/library/ms174313.aspx (Stored Procedure sp_who)
http://msdn.microsoft.com/en-us/library/ms179881.aspx (Tabela sys.processes)

Versão do SQL Server: 2005

Gravando e recuperando valor de um item da chave de registro do Windows

Hoje resolvi escrever um artigo de como trabalhar com o famoso registro do Windows.
Há algumas semanas atrás precisei manipular chave de registro do Windows em um software que estava desenvolvendo e não acreditei como é tão simples de gravar/recuperar valor de uma “chave de registro”.
Para realizar essas operações precisaremos importar a namespace Microsoft.Win32
Segue abaixo uma tabela com as classes necessárias e breve descrição:

Classe Descrição
Registry Oferece o conjunto de chaves-raiz padrão encontrado no Registro em máquinas rodando Windows.
RegistryKey Representa um nó de nível de chave no registro do Windows.Essa classe é um encapsulamento de Registry.

Agora vamos ver na prática um exemplo de manipulação de registro.
Eu criei um projeto do tipo “Console Application” e o código do meu método estático “main” ficou conforme abaixo:

 
static void Main(string[] args)
        {
            //Sempre recomendo colocar em try{} não sabemos se o mesmo retornará um erro
            try
            {
                //Abrindo sub chave "SOFTWARE" localizada no "HKEY_LOCAL_MACHINE\"
                RegistryKey reg = Registry.LocalMachine.OpenSubKey("SOFTWARE", true);

                //Criando sub chave "EXEMPLOREG"  dentro de "HKEY_LOCAL_MACHINE\SOFTWARE\"            
                reg = reg.CreateSubKey("EXEMPLO_REG");

                //Criando sub chave "LICENÇA" dentro de "HKEY_LOCAL_MACHINE\SOFTWARE\EXEMPLO_REG\"            
                reg = reg.CreateSubKey("LICENÇA");

                //Criando um item com nome "SERIAL" e valor "TESTANDO!" dentro de "HKEY_LOCAL_MACHINE\SOFTWARE\EXEMPLO_REG\LICENÇA"
                reg.SetValue("SERIAL", "TESTANDO!");
            }
            catch (Exception erro)
            {
                Console.WriteLine(erro.Message);
            }

            //Não utilizei o mesmo objeto para mostrar como que você faria o processo de recuperação do valor de um item em uma chave
            
            //Sempre recomendo colocar em try{} não sabemos se o mesmo retornará um erro           
            try
            {
                //Recuperando valor do item "SERIAL" dentro de "HKEY_LOCAL_MACHINE\SOFTWARE\EXEMPLO_REG\LICENÇA"
                Console.WriteLine(Registry.LocalMachine.OpenSubKey("SOFTWARE").OpenSubKey("EXEMPLO_REG").OpenSubKey("LICENÇA").GetValue("Serial"));
            }
            catch (Exception erro)
            {
                Console.WriteLine(erro.Message);
            }
            Console.ReadLine();
        }

Como pode ser notado é muito simples trabalhar com registro.
Explore mais a classe Registry pois você consegue acessar várias chaves-raiz padrão do Windows, por exemplo Registry.CurrentUser você consegue acessar a chave HKEY_CURRENT_USER
Até o próximo artigo!
Abraços,

João Paulo

IsolatedStorage

Algum dia você vai se deparar ou já se deparou com o seguinte problema: “como armazenar (sem utilizar um Banco de Dados ou outros meios) informações de perfil na sua aplicação se o usuário que executa tem acesso restrito na estação?”.
Através da utilização de IsolatedStorage você poderá solucionar facilmente este típico cenário, mas o que é afinal IsolatedStorage? Como o próprio nome diz é uma área isolada onde podemos gravar dados sem precisar se preocupar com qual nível de acesso o usuário que está executando nossa aplicação possui.
Existem algumas classes maravilhosas contidas dentro da namespace System.IO e System.IO.IsolatedStorage que oferece esses recursos. Vamos então conhece-las, segue abaixo uma tabela com as classes e breve descrição:

Classe Descrição
IsolatedStorageFile Oferece funcionalidades básicas para criação de arquivos e diretórios dentro do IsolatedStorage.
IsolatedStorageStream Oferece funcionalidades básicas para criar arquivos e seu fluxo para ler ou gravar dados dentro de uma IsolatedStorage, essa classe deriva da FileStream e seu uso é quase idêntico ao mesmo.
StreamReader Oferece funcionalidades básicas para ler dados de um fluxo, quer seja ele: HD, Memória e Rede.
StreamWriter Oferece funcionalidades básicas para gravar dados em um fluxo, quer seja ele: HD, Memória e Rede.

Deixando um pouco de lado teoria para codificar :-)
Vamos montar um projeto do tipo console e o nome fica ao seu critério. Coloque o seguinte código dentro do método estático main:

 
//Recuperando o local do IsolatedStorage onde será armazenado os dados            
           IsolatedStorageFile userStore = IsolatedStorageFile.GetUserStoreForAssembly();

            //Verificando se o arquivo já existe            
            string[] files = userStore.GetFileNames("UserConfig.set");
            //userStore.DeleteFile("UserConfig.set");
            //Este processo seria parecido com o File.Exists
            if (files.Length.Equals(0))
            {
                //Criando um fluxo de dados
                IsolatedStorageFileStream userStream = new IsolatedStorageFileStream("UserConfig.set", FileMode.Create, FileAccess.ReadWrite, userStore);

                //Criando um objeto para gravar os dados no fluxo
                StreamWriter userWriter = new StreamWriter(userStream);

                //Gravando o texto Configuração do usuário no fluxo
                userWriter.WriteLine("Configuração do usuário");

                //Fechando o fluxo e persistindo o dado no arquivo
                userWriter.Close();
            }
            
            files = userStore.GetFileNames("UserConfig.set");
//Este processo seria parecido com o File.Exists
            if (files.Length>0)
            {
                //Criando um fluxo de dados
                IsolatedStorageFileStream userStream = new IsolatedStorageFileStream("UserConfig.set", FileMode.Append, FileAccess.Write, FileShare.None, userStore);

                //Criando um objeto para gravar os dados no fluxo
                StreamWriter userWriter = new StreamWriter(userStream);
                for (int i = 0; i < 5; i++)
                {
                    //Gravando o texto Configuração do usuário no fluxo
                    userWriter.WriteLine(i.ToString() + "- Configuração do usuário");
                }
                //Fechando o fluxo e persistindo o dado no arquivo
                userWriter.Close();

                //Criando um fluxo de dados
                userStream = new IsolatedStorageFileStream("UserConfig.set", FileMode.Open, FileAccess.Read, FileShare.None, userStore);

                //Criando um objeto para ler os dados no fluxo
                StreamReader userReader = new StreamReader(userStream);

                //Lendo dados do arquivo do ínicio até o fim
                string contents = userReader.ReadToEnd();

                //Exibindo no console
                Console.WriteLine(contents);

                //Fechando o fluxo
                userReader.Close();

            }

Depois de analisado os comentários pressione Crtl + F5 e veja o resultado.
É os dados foram gravados e lidos, detalhe, a onde está o arquivo??
Lembra do método IsolatedStorageFile.GetUserStoreForAssembly(); ?
Pois é os dados estão neste local, mas a onde fica no windows?
Como esse método retorna local por usuário e Assembly (.Exe), você encontrará em:
C:\Documents and Settings\<Nome do
usuário que executou>\Configurações locais\Dados de
aplicativos\IsolatedStorage\

Espero ter ajudado e ampliado um pouco mais seus horizontes, até o próximo post.

Abraços,

João Paulo

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.