quinta-feira, 26 de abril de 2007

Usando try...catch no SQL Server 2005

Olá.
Venho hoje falar sobre este novo recurso da linguagem Transact-SQL (T-SQL) do SQL Server 2005.

Nas versões anteriores do SQL Server a única maneira de se trabalhar com exceções era o famoso @@ERROR.
Usávamos este recurso principalmente quando tínhamos uma transação. Era comum que, após iniciarmos a transação, tivéssemos que incluir abaixo de cada linha com potencial de erro o seguinte código:

IF @@ERROR > 0
ROLLBACK TRANSACTION

O tratamento de erros desta maneira possuía várias desvantagens, dentre elas posso citar:

  • Ter de escrever este código em cada linha que poderia ocasionar em um erro;
  • A variável @@ERROR era reinicializada após qualquer outro comando;
  • Os erros não poderiam ser capturados e tratados pelo próprio código (procedure), ou seja, após realizarmos o “ROLLBACK” o erro era lançado para a próxima procedure ou para a aplicação da pilha;


A grande mudança no T-SQL é que agora podemos tratar os erros de um trecho de código quase da mesma forma que fazemos no VB.Net ou no C#.

O procedimento é bem simples:

  1. Iniciamos o bloco que pode retornar um erro que queremos tratar com “BEGIN TRY”;
  2. Escrevemos nosso código normalmente, inclusive com a inicialização da transação e o “COMMIT TRANSACTION” no final;
  3. Finalizamos o bloco com “END TRY”;
  4. Abrimos o bloco de tratamento de erros com “BEGIN CATCH”;
  5. Escrevemos nosso código de tratamento do erro;
  6. Fechamos o bloco de tratamento de erros com “END CATCH”;

É muito importante atentar para o fato de que, ao capturar uma exceção em um bloco CATCH, o SQL Server não a lança para quem chamou o código. Isto quer dizer que, se você necessitar que o erro seja lançado para o caller é necessário utilizar do nosso velho conhecido RAISERROR.

Veja um exemplo de código de como isto pode ser feito:

begin try
begin transaction
seu código vem aqui
commit transaction
end try
begin catch
declare
@ErrorMessage nvarchar(4000)
declare @ErrorSeverity int
declare @ErrorState int

select
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE()

rollback transaction

RAISERROR
(@ErrorMessage, @ErrorSeverity, @ErrorState)
end catch

Você notou as novas funções de erro?
Bem mais informativas que a antiga @@ERROR.

No SQL Server 2005, as seguintes funções são utilizadas para obter mais detalhes dos erros:

ERROR_NUMBER()
ERROR_SEVERITY()
ERROR_STATE()
ERROR_PROCEDURE()
ERROR_LINE()
ERROR_MESSAGE()

Além de fornecer detalhes sobre o erro ocorrido, estas funções têm como vantagem o fato de não serem reinicializadas após uma linha qualquer de comando executado, como acontecia com o @@ERROR.

A grande vantagem do TRY...CATCH é que, além de deixar o código mais robusto, podemos separar o que é a lógica do negócio do tratamento dos possíveis erros.

Diminuímos a quantidade de código escrito e temos uma melhor legibilidade.

Mais informações em Using TRY...CATCH in Transact-SQL.

Abraços e até o próximo post.

sexta-feira, 20 de abril de 2007

Método Page_Load é disparado duas vezes

Olá. Venho hoje compartilhar uma solução para um problema muito estranho ocorrido após a migração de alguns projetos web do Visual Studio 2003 para o Visual Studio 2005.
Basicamente o que ocorria é que os webforms migrados disparavam seu método Page_Load duas vezes em uma requisição.
Após algumas pesquisas no Google e na própria MSDN todas as soluções apontavam que o problema estava na propriedade “AutoEventWireup” da página. Esta propriedade, segundo os posts, estaria configurada como “True” quando na verdade o correto seria “False”.
Estaria tudo resolvido não fosse o fato de que nas minhas páginas esta propriedade já estava em “False”.
O mais interessante é que as novas páginas criadas já no Visual Studio 2005 não apresentavam o mesmo problema.
Por algum tempo fiquei a tentar contornar este problema até que, por fim, notei uma pequena diferença na declaração do método Page_Load.

Vejam a diferença:

- Método Page_Load de uma página migrada do VS2003 para o VS2005

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load, Me.Load

- Método Page_Load de uma página nova no VS2005

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load

Notaram que no primeiro caso o método Page_Load “escuta” dois eventos, um referente ao Load do MyBase e outro referente ao Load da própria página?

Para tentar chegar à raiz do problema, criei um novo projeto web no VS2003 e notei que nele, uma nova página criada, o Page_Load escuta o MyBase.Load, enquanto que no VS2005 o Page_Load escuta o Me.Load.
Isto se dá basicamente por causa da mudança que houve no modelo de compilação do ASP.Net 2.0. Enquanto no VS2003 uma nova página era criada com duas classes, uma para a página e outra para o codebehind, no VS2005 a página e o codebehind são a mesma classe.
No VS2003 era usado o sistema de herança entre as duas classes, daí a necessidade de se escutar o evento Load do MyBase. Já o VS2005 usa o novo recurso de classes parciais onde ambos, página e codebehind, pertencem à mesma classe.
O recurso de classes parciais nada mais é que poder escrever uma mesma classe em diversos arquivos. Este recurso soluciona vários problemas ocorridos até então como, por exemplo, a separação de um código gerado automaticamente (por uma ferramenta qualquer) de um código criado pelo desenvolvedor. Até então, quando gerávamos novamente o código automático, tínhamos que tomar o cuidado de separar e reescrever no novo arquivo o código criado pelo desenvolvedor.

Para mais informações sobre classes parciais, acesse este artigo da MSDN: http://www.microsoft.com/brasil/msdn/Tecnologias/vbnet/vs04k1.mspx#EFB. Além de classes parciais são abordadas outras mudanças ocorridas no Visual Basic 2005.

Outros problemas encontrados com a migração de projetos VS2003 para o VS2005 são relatados por Ben Aminnia em http://www.pointercorp.com/Convert_ASPDOTNET_11_20.htm.

Boa migração e até o próximo post.

segunda-feira, 16 de abril de 2007

O projeto LINQ

Hoje, arrumando os livros de minha estante, deparei-me com uma publicação que recebi do Alexandre Nardi, Arquiteto de Soluções da Microsoft Brasil, em um evento realizado aqui em Brasília no ano passado.
Nesta publicação estão textos cuidadosamente selecionados pela equipe da MSDN Brasil que abordam desde expansão do Agile para adequação ao CMMI Nível 3, até os novos recursos de segurança dos dados com o SQL Server 2005.
Todos estes textos podem ser encontrados em www.microsoft.com/brasil/msdn/arquitetura, porém o que mais me chamou a atenção neste momento foi o artigo “O Projeto LINQ - .NET Language Integrated Query” (www.microsoft.com/brasil/msdn/Tecnologias/arquitetura/LINQ.mspx).
O artigo foi exemplarmente escrito em setembro de 2005 e, apesar do tempo passado, continua sendo uma excelente fonte para compreensão do que vem a ser o LINQ e de como esta tecnologia vai impactar na maneira como programamos e tratamos os dados relacionais.
Neste processo de compreensão do LINQ tem-se como conseqüência a compreensão da dimensão e da importância de alguns novos recursos das linguagens C# e VB.Net, como por exemplo os tipos genéricos, métodos e classes anônimas e operadores de consulta ou agregação. Alguns destes recursos já estão a nossa disposição (principalmente em C#), mas para todos os outros deveremos esperar o Visual Basic 9.0 e o C# 3.0.
Boa leitura e até o próximo post.

Estréia

Olá, esta é a primeira postagem de muitas que virão.
Como citado na apresentação do blog, este espaço não possui qualquer pretensão maior a não ser trazer informações relevantes nas áreas as quais se propõe. Não esperem encontrar aqui textos que já foram exaustivamente explorados por outros sites. Também não esperem uma periodicidade alemã na publicação dos textos porque nem sempre terei algo tão relevante que mereça virar um post. Mas podem contar que cada informação, cada parágrafo e cada dica possuirão relevância e, de preferência, abordarão uma solução para um problema real sofrido por mim como desenvolvedor no dia-a-dia.
Desde já agradeço a atenção e a paciência e espero contribuir um pouquinho que seja para esta grande comunidade. Abraços e até o primeiro texto técnico.