Programação Orientada à Objetos Aula 16- Tratamento de Exceções ADO.NET – Tratando Exceções (Erros) Qualquer pessoa que já foi um simples usuário de uma aplicação já se deparou com alguma mensagem de erro na sua tela. Algumas aplicações não tratam tais erros (exceções) de forma correta e deixam que os usuários recebam mensagens que só são entendidas pelo programador - e que não ajudam em nada o usuário. O tratamento de exceções consiste em interceptar esses erros fim de que o programa não aborte inesperadamente e ainda, consiga informar ao usuário o que está errado. ADO.NET – Tratando Exceções (Erros) No C# as exceções (ou exceptions) são tratadas com as instruções try, catch e finally. A idéia consiste em proteger um bloco de código com o try e, caso ocorra algum erro, a exceção gerada será capturada pelo bloco catch. Dentro do bloco catch geralmente exibimos uma mensagem (MessageBox) para o usuário, explicando-lhe que houve um erro. Caso seja necessário sempre executar uma determinada ação (código) ao final, não importando se foi OK ou se deu algum erro, inserimos tal código num bloco finally. ADO.NET – Tratando Exceções (Erros) Resumindo: • try - define o bloco que contem a execução normal do código; • catch - define o bloco com o código que será executado caso ocorra alguma exceção dentro do bloco protegido pelo try. Aqui é feito o tratamento de erros; • finally (opcional) - define o bloco que será executado independentemente se ocorreu uma exceção ou não. ADO.NET – Tratando Exceções (Erros) Na prática: A seguir a interface e o código de um formulário que tem por objetivo calcular a área de um triângulo: ADO.NET – Tratando Exceções (Erros) Evento click do botão ADO.NET – Tratando Exceções (Erros) O código acima funciona perfeitamente mas não prevê erros. Se por acaso clicarmos no botão com os campos vazios ou letras no lugar de números o programa vai exibir uma mensagem padrão do .NET, indicando que ocorreu uma exceção e o código será interrompido. ADO.NET – Tratando Exceções (Erros) A mensagem padrão de erro será parecida com esta: O que o usuário irá pensar ao ver esta mensagem?!? :( ADO.NET – Tratando Exceções (Erros) Agora vejamos o código com tratamento de erro simples. Nesse caso, se ocorrer algo errado uma mensagem mais amigável será exibida no lugar da mensagem de erro padrão do .NET. ADO.NET – Tratando Exceções (Erros) Agora, se o usuário não informar os dados e clicar no botão, a mensagem que será exibida será assim: ADO.NET – Tratando Exceções (Erros) Exemplo do finally Vamos imaginar que a gente queira limpar o conteúdo dos textBox ao final, não importando se deu certo ou se deu erro. Para isso, basta adicionar um bloco finally com o código correspondente. A seguir o código completo com a instrução finally: ADO.NET – Tratando Exceções (Erros) ADO.NET – Tratando Exceções (Erros) Exercício 1 Agora crie um projeto chamado ProjTratamentoExcecao e reproduza o exemplo citado anteriormente (ou similar). Execute e teste sua aplicação. ADO.NET – Tratando Exceções (Erros) Quando trabalhamos com BD as exceções geralmente ocorrem em dois momentos: 1. Ao tentar conectar com o BD; 2. Ao executar um comando SQL. ADO.NET – Tratando Exceções (Erros) Os erros que ocorrem na hora da conexão com o BD frequentemente estão associados a: • String de conexão inválida (errada). • Servidor de BD não existe ou não está acessível. • Falha no login (usuário e/ou senha inválidos). Já os erros mais comuns quando tentamos executar um comando SQL são: • Sintaxe incorreta do comando SQL (SELECT, UPDATE, INSERT e DELETE). • Nome da tabela ou coluna incorretos. ADO.NET – Tratando Exceções (Erros) Vimos também que podemos tratar os erros ocorridos na aplicação através da estrutura try..catch..finally. Agora vamos aprender um pouco mais sobre as exceções em .NET. ADO.NET – Tratando Exceções (Erros) Toda exceção lançada por um programa em .NET pertence à classe Exception (System.Exception). Isto significa que a classe de uma exceção sempre será System.Exception ou uma de suas sub-classes, por exemplo, FormatException ou DivideByZeroException. ADO.NET – Tratando Exceções (Erros) Vamos criar uma aplicação para ficar mais claro. Crie o projeto ProjTratamentoExcecoes e configure o formulário principal da forma ilustrada a seguir: ADO.NET – Tratando Exceções (Erros) Este programa irá receber a base e a altura de um triângulo e então calcular e exibir a sua área em um MessageBox. Digite o código a seguir no evento Click do botão: ADO.NET – Tratando Exceções (Erros) Perceba que a principal diferença entre o tratamento de erro usado aqui e o do exemplo anterior está no bloco catch, onde agora definimos a variável erro da classe Exception para que possamos acessar as informações do erro originado pelo .NET. O comando erro.Message irá retornar a mensagem de erro original, já o erro.GetType() retornará a classe da exceção gerada. ADO.NET – Tratando Exceções (Erros) Se agora executarmos nossa aplicação e clicarmos no botão sem preencher qualquer campo, receberemos a seguinte mensagem: ADO.NET – Tratando Exceções (Erros) Perceba que além de exibirmos a mensagem padrão ("Ocorreu um erro ao calcular a área"), temos outras informações: a mensagem de erro originado pelo .NET e a sua classe (FormatException). Agora outro teste. Se digitarmos valores muito grandes nos campos e clicarmos no botão a mensagem será: ADO.NET – Tratando Exceções (Erros) Veja como mudaram a mensagem original e a classe da exceção (OverflowException). Tanto FormatException como OverflowException são subclasses da classe Exception. A seguir um diagrama de classes UML para ilustrar melhor essa hierarquia de classes de exceções: ADO.NET – Tratando Exceções (Erros) Perceba que toda exceção possui uma classe ancestral em comum, a classe Exception. Através desta hierarquia podemos refinar/melhorar nossas mensagens de erro para o usuário. Podemos, por exemplo, exibir a mensagem "Digite apenas números para os campos" quando a classe da exceção for FormatException. E a mensagem "Valor informado está muito grande" quando a classe for OverflowException. E ainda, exibir a mensagem padrão "Ocorreu um erro ao calcular a área" no caso de qualquer outra exceção. Fazemos isso inserindo vários blocos catch – um para cada exceção que desejamos capturar e tratar separadamente. Veja o código de exemplo: ADO.NET – Tratando Exceções (Erros) ADO.NET – Tratando Exceções (Erros) Uma coisa importante a observar neste código é que, os blocos catch mais específicos (FormatException e OverflowException) devem ser digitados antes dos mais genéricos (Exception). Mas não se preocupe, se não tomarmos este cuidado, o compilador irá nos avisar exibindo uma mensagem de erro ao compilarmos o nosso programa. Como todas as exceções são classes elas possuem propriedades e métodos. Message é uma propriedade que nos informa a mensagem original do .NET e GetType() é um método que nos retorna a classe da exceção. Tanto Message como GetType() estão implementados na classe Exception e, portanto, estão acessíveis em todas as suas subclasses. ADO.NET – Tratando Exceções (Erros) A exceção SqlException Uma classe de exceção que muito nos interessa quando trabalhamos com acesso ao BD é a SqlException. Além das propriedades herdades de Exception ela possui outras, dentre elas podemos citar: • Number : informa o código interno do erro no BD. Cada erro lançado por um SGBD possui um código interno – estes códigos são diferentes para cada SGDB (MS SQL Server, Oracle, Postgres etc); • LineNumber : informa a linha do comando SQL onde ocorreu o erro. Com estas propriedades, podemos tratar as mensagens lançadas pelo BD, que são as exceções da classe SqlException, através do seu código e ainda informar qual a linha onde ocorreu o erro. ADO.NET – Tratando Exceções (Erros) Vamos a um exemplo prático. Abra o MS SQL Server Management Studio. Na tela inicial (onde informamos o servidor, usuário e senha) digite um servidor que não existe, por exemplo "teste123" e clique no botão 'Connect'. Receberemos então uma mensagem gerada pelo SGDB a qual conterá seu código interno, veja a imagem do erro: ADO.NET – Tratando Exceções (Erros) Percebam no destaque que o código interno do erro gerado pelo SQL Server foi 53. Podemos recuperar este código no C# e exibir uma mensagem de erro mais amigável para o usuário dessa forma: ADO.NET – Tratando Exceções (Erros) Exercício 2 Baseando-se no exemplo anterior, insira um tratamento de exceções adequado no projeto da aula anterior (ou similar) para que, ao clicar no botão 'Conectar ao BD', sejam tratadas as exceções de: servidor inválido, banco de dados inválido e usuário/senha inválidos. Como parte deste exercício, você terá que descobrir os códigos dos respectivos erros e implementá-los na sua aplicação. Dúvidas?