Páginas

sexta-feira, 9 de março de 2012

ORA-01843: not a valid month

Estou aqui de novo para comentar problemas relacionados ao desenvolvimento com Oracle, e como eles foram resolvidos.

Na equipe que trabalho entrou uma pessoa nova, e precisamos instalar o cliente do Oracle para que ele pudesse trabalhar. Após feita a instalação do Oracle Instant Client, quando ele começou a executar o sistema na sua máquina, o seguinte erro apareceu: ORA-01843: not a valid month. Detalhe que quando a mesma rotina era executada na minha máquina, eu não tinha esse problema.

Após algumas pesquisas, identificamos a causa. No banco de dados que estamos utilizando, a configuração de formato de data está parametrizado para dia/mês/ano:


select * from nls_database_parameters;

NLS_LANGUAGE                          AMERICAN
NLS_TERRITORY                          AMERICA
NLS_CURRENCY                          $
NLS_ISO_CURRENCY                  AMERICA
NLS_NUMERIC_CHARACTERS  .,
NLS_CHARACTERSET                  WE8ISO8859P1
NLS_CALENDAR                         GREGORIAN
NLS_DATE_FORMAT                 DD-MON-RR
NLS_DATE_LANGUAGE                  AMERICAN
NLS_SORT                                         BINARY
NLS_TIME_FORMAT                         HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT         DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT                 HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY                $
NLS_COMP                                        BINARY
NLS_LENGTH_SEMANTICS        BYTE
NLS_NCHAR_CONV_EXCP        FALSE
NLS_NCHAR_CHARACTERSET    AL16UTF16
NLS_RDBMS_VERSION               11.2.0.2.0


No entanto, na máquina do desenvolvedor não havia configuração de como o cliente do Oracle trataria as informações. Desse modo, ele estava considerando o retorno de formato de data como no padrão mês/dia/ano. Quando a rotina era executada, ela retornava uma data, digamos 16/02/11. No formado brasileiro, teríamos o 16 como dia, mas lendo isso no formado padrão, 16 seria o mês, o que não existe. Por isso ocorria o erro de not a valid month.

A correção foi incluir uma parametrização no registro do Windows informando que era para ser considerado o formato brasileiro. Ou seja, incluir a propriedade NLS_LANG com valor BRAZILIAN PORTUGUESE_BRAZIL.WE8MSWIN1252 dentro da chave HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraClient11g_home1 (este caminho pode variar, dependendo de como foi feita a instalação do cliente).


Mas muito importante, tivemos que reiniciar a máquina para essa parametrização surtir efeito. Depois disso, tudo funcionou ok.

Obs. Eu não sei se essa é a forma correta de corrigir o problema, mas foi o que funcionou. Se alguém conhecer um jeito mais elegante, por favor, comente aqui.

[]'s

quarta-feira, 7 de março de 2012

TransactionScope e Invalid operation. The connection is closed no Oracle

Tudo na vida acontece por uma razão, e quando a gente não entende a razão considera que é magia.

Digo isso por um problema que estava tendo em uma aplicação ASP.NET que usa banco de dados Oracle. Em determinada funcionalidade, um processamento com gravação, ocorria um problema que impedia a gravação dos registros. O erro era:

System.InvalidOperationException: Invalid operation. The connection is closed.
   at System.Data.OracleClient.OracleConnection.GetOpenInternalConnection()
   at System.Data.OracleClient.OracleConnection.get_ErrorHandle()
   at System.Data.OracleClient.OracleDataReader.ReadInternal()
   at System.Data.OracleClient.OracleDataReader.Read()
   at Microsoft.Practices.EnterpriseLibrary.Data.Oracle.OracleDataReaderWrapper.Read()

Simplesmente eu não entendia a causa desse erro ( neste momento chamado de "magia"), pois o código que rodava essa consulta (sim, consulta, pois você pode ver que na stacktrace estamos usando o DataReader do OracleClient) funcionava de forma isolada sem problemas. Essa conclusão eu cheguei após gerar um windows service e colocar para ficar rodando este método a cada 30 segundos, já que minha primeira desconfiança era algum problema esporádico de comunicação com o servidor Oracle. Bom, esse windows service ficou rodando por horas, sem apontar nenhum problema.

No final do dia, uma coisa me chamou a atenção: processamentos pequenos funcionavam sem problema, os que gravavam muitos dados é que geravam o erro. E mais, todo o código que era executado estava envolvido por um TransactionScope... Na altura do campeonato, resolvi testar tirando a transação, ou seja, passando no seu construtor a opção Suppress (http://msdn.microsoft.com/en-us/library/ms172152(v=vs.90).aspx):

using(var trans = new TransactionScope(TransactionScopeOption.Suppress)) 
{
    // ...
} 

Dito e feito. Após essa alteração, o código funcionou.

Mas não deixei a rotina assim. Para não ficar com ela de forma que pudesse dar alguma inconsistência na gravação do banco, eu mantive a transação ativa só que coloquei um tempo de timeout maior (http://msdn.microsoft.com/en-us/library/9wykw3s2.aspx). Também funcionou e resolveu o problema.

Em resumo, o problema do Invalid Operation dava quando o tempo de transação padrão, que é 60 segundos, expirava no meio do processamento. Isso impactava também a parte das leituras que eram feitas na base de dados. O problema que eu classifiquei como "magia" poderia ser traduzido como uma descrição de erro não clara. Se logo no começo eu tivesse tomado um erro cuja descrição falasse algo de transação, ficaria mais claro para ir direto na raiz do problema. Mas fica a dica de que tudo tem explicação, só depende de quão fundo você pode e quer ir.

Em tempo, essa rotina que estava com problemas poderia ser melhor escrita. Ou seja, antes de iniciar a transação de gravação, ler e processar tudo o que fosse necessário, deixando apenas para gravar os dados no banco em um último momento e com transação somente nesta parte. Assim que possível vamos fazer isso.

[]'s

quinta-feira, 16 de fevereiro de 2012

Mau uso do TryParse...

Abaixo está uma pérola onde vemos o uso incorreto do método TryParse. Temos uma string, lida de um arquivo, que contém informação de data, e é necessário colocá-la em um objeto do tipo DateTime. Veja como foi feito abaixo.

public DateTime ObterDataControle()
{
    DateTime dt = DateTime.MinValue;

    if (File.Exists(_caminhoArquivo))
    {
        StreamReader sr = new StreamReader(_caminhoArquivo);
        try
        {
            string dateString = sr.ReadLine();

            if (DateTime.TryParse(dateString, out dt))
                dt = Convert.ToDateTime(dateString);
        }
        finally
        {
            sr.Close();
        }
    }
    return dt;
}

O método TryParse retorna um bool, que indica se foi possível converter a string para o determinado tipo. Só que quando é possível efetuar a conversão, este método já coloca o valor no parâmetro que ele recebe de output. Não é necessário fazer (como foi feito no código) uma nova conversão do valor. A linha dt = Convert.ToDateTime(dateString) é totalmente desnecessária.

[]'s

segunda-feira, 9 de janeiro de 2012

Impressões da 70-512

No final do ano passado (alias, feliz 2012 para todos!) eu fiz a prova de certificação da Microsoft 70-512, de administração do TFS. Felizmente ocorreu tudo ok, e eu passei! E agora vou colocar neste espaço aqui alguns comentários e impressões que eu tive dela, para servir de dica para que irá fazê-la em breve.

Bom, em primeiro lugar, eu vou passar como eu me preparei para a prova:

  1. Antes mesmo de pensar em fazer essa prova, eu tive oportunidade de assistir um treinamento de ALM com meu amigo Victor Cavalcante. Boa parte do conteúdo deste treinamento caiu na prova. Se tiverem oportunidade, procurem algum treinamento com pessoal capacitado como ele.
  2. Já quando eu estava com a idéia de fazer a prova (meta da empresa), eu encontrei o livro Professional Team Foundation Server 2010. É um bom livro, apesar que eu achei que algumas partes deixaram a desejar, como a parte de Lab Management e configuração de servidores Proxy do TFS. Mas a visão geral da parte de instalação e configuração e uso de branchs compensa. No final, o livro é um bom material para estudo dessa prova.
  3. Encontrei também alguns links com material online para estudo, como este aqui http://dfaoliveira.wordpress.com/2010/10/08/exame-70-512/ do Daniel Oliveira. Tem bastante links interessantes.
  4. Baixei a máquina virtual que a Microsoft disponibiliza para testes, pois com ela tive um ambiente já pronto para brincar um pouco: http://www.microsoft.com/download/en/details.aspx?id=22267.

Basicamente a estratégia de estudo que eu segui foi essa. Agora vou comentar um pouco da prova.

A 70-512 é uma prova bem conceitual, você não precisa saber detalhes da administração para fazê-la. Por exemplo, lembro de uma questão onde era dado um cenário onde se devia tirar um team project de uma team project collection e passar para outro. A solução neste caso seria fazer um split (http://msdn.microsoft.com/en-us/library/dd936158.aspx), e bastava saber esse conceito para ter a resposta. Não precisava saber dos detalhes que tem nesse último link que passei, apenas uma visão geral.

Outra coisa que pega bastante a parte conceitual da coisa são as questões que envolvem instalação e configuração. São várias onde é dado um cenário (a pessoa instalando um TFS em várias máquinas, fazendo upgrade, etc) e é questionado quais opções de configuração escolher. Isso foi um assunto que eu bloguei alguns dias antes da prova (http://www.galorebr.blogspot.com/2011/12/resumo-tipos-de-configuracao-do-tfs.html). Pré-requisitos de servidores, como o uso do WSS 3.0 para integração mínima com Sharepoint, também são cobrados.

Caiu uma questão de restauração de desastres relacioada ao Reporting Services, mais especificamente sobre a necessidade de fazermos um backup da symmetric key. Mas em geral as questões ficam com foco mesmo no TFS, não na configuração da infra necessária.

Outro tipo de questão que cai bastante é relacionado ao uso de branch e merge. Geralmente a questão vai envolver a escolha da alternativa que mostra como disponibilizar certas alterações de código feita em uma branch em uma outra branch, sem o uso de um baseless merge (http://msdn.microsoft.com/en-us/library/bb668976.aspx). Basicamente escolha a questão que explique um caminho de “merges” desde a branch de origem até a de destino.

Sugiro também dar uma “decorada” nas opções disponíveis quando enfileiramos um build, por exemplo para ativar a execução de testes, impacto dos testes ou Code Analysis. Caem também alguns comandos (lembro de uma questão relacionada ao “tf /lock”). Ah, também foram cobrados conceitos de shelveset e cloak, sendo que a questão dá um cenário por exemplo desenvolvedor querendo que alterações ainda não finalizadas ficassem no backup do TFS ou evitar que arquivos desnecessários sejam baixados na máquina durante o processo de get latest version.

Por enquanto ficam essas dicas, mas se eu lembrar de mais coisas eu atualizo este post.

Boa sorte para todos que forem fazer essa prova.

[]’s

domingo, 25 de dezembro de 2011

Resumo: tipos de configuração do TFS 2010

O TFS possui os processos de instalação e configuração bem segregados. No primeiro processo, é possível escolher o que será instalado na máquina. No segundo, podemos escolher quais componentes habilitar, quais instâncias do SQL utilizar, etc. Hoje vamos falar de configuração, e abaixo estão os tipos disponíveis para configuração do TFS.

  • Basic – Permite configurar o TFS para usar o controle de versões, work-items e a parte de testes e lab management. No entanto, não permite a integração com Sharepoint e Reporting Services (cenário, por exemplo, quando instalamos o TFS num sistema operacional cliente, como o Windows 7).
  • Standard – É a configuração que deve ser escolhida ao se instalar o TFS em uma única máquina, mas funciona apenas com Windows Sharepoint Services 3.0. Não permite a escolha de um SQL Server remoto.
  • Advanced – Agora sim, permite usar SQL Server, Sharepoint e Reporting Services remotos. É nela que temos a maior flexibilidade de configuração.
  • Application-Tier Only – É usada na configuração de ambientes com alta disponibilidade (adicionando servidores em um Network Load Balance, por exemplo). Também pode ser usada em cenários em que se move a camada de aplicação do TFS para outra máquina ou em situações de recuperação de desastres.
  • Upgrade – Como o nome diz, deve ser utilizado em situações de upgrade do TFS 2005 ou 2008.
  • Configure Team Foundation Server Proxy – Para quando instalamos o TFS Proxy Server.
  • Configure Team Foundation Build Service – Para quando a máquina onde instalamos o TFS servirá como Build Agent ou Controller.
  • Configure Extensions for SharePoint Products – Configura extensões no Sharepoint para que o TFS possa utilizar (em situações de Sharepoint remoto ou web farm).

O quadro abaixo dá um resumo por cima das 4 primeiras configurações, mostrando suas principais diferenças.

 

  Basic Standard Advance Application-Tier only
Instâncias Multiple-server Single-server Multiple-server Multiple-server
Reporting Não Sim Sim Sim
Sharepoint Integration Não Sim Sim Sim
SQL em outra máquina Sim Não Sim Sim

Se pensarmos num ambiente corporativo com muito uso do TFS (servidores segregados, ou seja, dados, aplicação, Sharepoint e Reporting Services tudo sepadados), basicamente iremos utilizar a configuração Advanced para configurar o primeiro servidor de aplicação (considerando escolher e configurar o SQL Server, Sharepoint, etc.) e depois a configuração Application-Tier only, para configurar os diversos nós do load balance.

Por hoje é só.

[]’s