VB .NET - Curso Prático ADO .NET - Desenvolvendo uma aplicação : Tratando exceções - VI


Na sexta parte do nosso curso prático vou abordar o tratamento de exceções em aplicações VB .NET.

Capturar e tratar erros (exceções) é uma das tarefas obrigatórias para todo o programador. O VB.NET trouxe uma novidade que nos auxilia no tratamento de erros : o bloco try-catch-finally. (Se você conhece Java esta em casa...).

O bloco try-catch-finally é usado para envolver o código onde existe a possibilidade de uma exceção/erro ocorrer. Um bloco try-catch-finally é constituído das seguintes seções :

  1. O código que pode gerar uma exceção é colocando dentro do bloco try
  2. Se o erro/exceção ocorrer o bloco catch entra em ação e o você faz o tratamento do erro
  3. Dentro do bloco finally você coloca o código que deverá ser executado sempre quer ocorra ou não a exceção.
Try
 
 'Código que pode gerar(levantar)  um erro.
Catch
   '
Código para tratamento de erros.
Finally
  
'Código de execução obrigatória.
End Try

Obs: O VB.NET ainda mantém , por questões de compatibilidade ,  a sintaxe : "On Error Goto" e você ainda pode usá-la mas prefira usar a estrutura try-catch.

A estrutura try-catch-finally é mais poderosa que a sintaxe anterior pois além de permitir a você fazer um aninhamento de vários tratamentos de erros na mesma estrutura , torna o código mais fácil de ler e manter.

Exemplo:

Sub Main()
     'Este código gera um erro/exceção

try
     Console.WriteLine("Vamos dividir 10 por 0 para ver o que acontece...")
     Console.WriteLine()

     Dim i As Integer = 10
     Dim j As Integer = 0
     Dim k As Integer

     ' Esta linha vai gerar um erro
   
 k = (i / j)

catch

     Console.WriteLine("Ocorreu um erro fatal... ")

End Try

End Sub

Capturando Múltiplas Exceções

Você pode detalhar ainda mais o seu tratamento de erros prevendo múltiplas exceções e tratando-as. Vejamos como fica o nosso exemplo :

Dim i As Integer = 2147483647
Dim j As Integer = 0
Dim k As Integer = 0

Try
  i+ = 1
  k=i/j
Catch exc As
DivideByZeroException
  Console.WriteLine("Erro: Divisão por zero")
Catch exc As
OverflowException

  Console.WriteLine("Erro: Overflow")
Finally
  Console.ReadLine()
End Try

Neste código estamos prevendo duas exceções :  Divisão por zero e Overflow. Isto permite uma detalhamento do erro facilitando a localização de sua origem. Naturalmente você não vai querer tratar todas as exceções possíveis ; neste caso você  usa um bloco catch genérico que trate os erros não previstos, algo como o código abaixo:

  1. Catch exc As Exception
         Console.WriteLine("Erro: " & exc.Message)

Tratamento de erros com Banco de dados

As aplicações que utilizam banco de dados tem que dar uma atenção especial ao tratamento de exceções , primeiro pela própria natureza da operação e de sua importância segundo por que ainda hoje , apesar de todos os esforços dos fabricantes , a interação com banco de dados esta sujeita a falhas.

 

Quando você utiliza o.NET Framework com banco de dados tem a disposição classes que representam exceções que podem ser disparadas quando um programa tenta se comunicar com um banco de dados. Geralmente as falhas ocorrem e são detalhadas quando da utilização dos comandos SELECT, INSERT , UPDATE e DELETE.

 

As duas classes principais são : OleDbException e SqlException que pertencem aos namespaces OleDb e SqlClient. Para obter realizar o tratamento das exceções geradas e obter seus detalhes utilizamos o bloco Try/Catch.  Estas classes retornam uma coleção de erros , e, com isto em mente , você pode expor todos os erros retornados em OleDbException e SqlException percorrendo a coleção de erros.

 

- A classe OleDbException dispara uma exceção relacionada com o provedor OleDb. (Esta classe não pode ser herdada.).
- A classe é criada sempre que um provedor OleDB .NET encontra um erro gerado a partir do servidor (os erros do lado do cliente são disparados como exceções padrão URT).
- A classe sempre contém no mínimo uma instância de OleDBError
- Se a gravidade do erro for muito severa o servidor pode fechar a conexão OleDbConnection.

 

Seus principais membros são :

ErrorCode Overridden. Obtém o  HRESULT do erro
Errors Obtém a coleção de um ou mais objetos OleDbError que dão informações detalhadas sobre as exceções geradas pelo provedor.
HelpLink (herdada de Exception) Obtém ou define um link para o arquivo de ajuda associado com a exceção.
InnerException (herdada de Exception) Obtém a instância da exceção que causou a exceção atual.
Message  Obtém o texto descrevendo o erro.
Source  Obtém o nome do provedor OLE DB que gerou o erro.
StackTrace (herdada de Exception) Obtém uma string representando da chamada da pilha da exceção disparada.
TargetSite (herdada de Exception) Obtém o método que disparou a exceção atual.

Exemplo:

Imports System.Data.OleDb
Module Module1

Sub Main()
    ' Cria uma string com instrução SQL
      Dim aQuery As String = "SELECT Nome FROM Clientes"
     ' Estou instanciando uma conexão OleDbConnection INVÁLIDA (adivinha porque ?)' e atribuindo-a a uma variável aConexao
     Dim aConexao As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;DataSource=")
     Dim aComando As New OleDbCommand(aQuery, aConexao)
     'inicio tratamento de exceções usando try/Catch
     Try

        ' Como temos uma OleDbConnection Inválida' uma exceção será disparada

         aComando.Connection.Open()
     Catch ex As OleDbException
        ' Exibe a mensagem genérica para a exceção
        Console.WriteLine(ex.ToString)
        Console.WriteLine()
        ' Percorre a coleção de erros em OleDbException' retornado pelo banco de dados
         Dim i As Integer
         For i = 0 To ex.Errors.Count - 1
            ' Exibe detalhes sobre os erros
             Console.WriteLine("Message: " & ex.Errors(i).Message)
             Console.WriteLine("NativeError: " & ex.Errors(i).NativeError)
             Console.WriteLine("Source: " + ex.Errors(i).Source)
             Console.WriteLine("SQLState: " + ex.Errors(i).SQLState)
         Next i
          Console.ReadLine() 
      End Try
 End Sub
End Module

Criando uma exceção personalizada

Uma exceção é uma condição de erro ou comportamento inesperado que ocorre durante a execução de um programa afetando  o fluxo normal da execução das instruções.

A plataforma .NET fornece a classe chamada System.Exception . Esta classe é a classe base para todas as exceções. Ela contém as seguintes propriedades:

Abaixo temos algumas das classes de exceções mais utilizadas :

System.ArithmeticException - Classe base para exceções que ocorrem durante operações aritméticas. Ex: System.DivideByZeroException e System.OverflowException.
System.ArrayTypeMismatchException - é lançada quando um objeto incompatível esta sendo armazenado em um array.
System.DivideByZeroException
- Ocorre quando há uma tentativa de dividir um número por zero.
System.IndexOutOfRangeException
- é lançada quando se tenta acessar um arrary usando um índice que menor que zero ou maior que o máximo índice permitido.
System.InvalidCastException - lançada quando um uma conversão de tipo explícita de um tipo base para um tipo derivado falha em tempo de execução.
System.NullReferenceException - Lançada quando um objeto ao ser acessado possui uma referência nula.
System.OutOfMemoryException - é lançada quando não há memória suficiente para realizar a operação.
System.OverflowException - é lançada quando em uma operação aritmética ocorre overflow.
ArgumentException - Lançada quando um argumento fornecido para o método não é válido.

Para criar sua exceção personalizada tudo o que você precisa fazer é criar uma classe que herde da classe Exception ou da classe Application.Exception.

Exemplo:

Imports System
Namespace Exp
   Public Class MyException Inherits Application.Exception
      Public Sub New()
           MyBase.New()
      End Sub
      Public Sub New(ByVal message As String)
          MyBase.New(message)
      End Sub
      Public Sub New(ByVal message As String, ByVal exp As Exception)
         MyBase.New(message, exp)
      End Sub
   End Class
End Namespace

Qual a melhor maneira de usar e tratar exceções em uma aplicação VB.NET ?

Creio que você já está consciente que deve procurar capturar diferentes tipos de exceções e saber o que fazer com cada uma delas em uma aplicação VB.NET. Existirão momentos que você deverá lançar uma exceção avisando o usuário de forma amigável para o problema que esta ocorrendo em outras ocasiões você deverá efetuar um tratamento mas elaborado.

De forma geral existem três formas de abordar o problema de tratamento de exceções :

  1. Você captura todas as exceções

  2. Você passa adiante todas as exceções

  3. Você cria sua própria exceção customizada e mapeia todas as exceções para esta classe.

A melhor forma de tratar o problema é a terceira opção onde você cria uma classe de exceção customizada.

Quando você cria um tipo de exceção customizada você ganha controle em todas as propriedades da exceção e pode também incluir propriedades a sua classe customizada.

Nota: A linguagem Java todos os métodos usam a instrução throw para lançar uma exceção. A instrução throw requer um argumento simples: um objeto que seja passível de ser lançado. Em Java objetos passíveis de serem lançados são instâncias de qualquer sub-classe da classe Throwable. Se você tentar lançar um objeto que não seja passível de ser lançado o compilador vai recusar na compilação do programa e indicar um erro. A cláusula throws especifica quais exceções o  método pode lançar. Você usa a instrução throws na assinatura do método informando quais exceções está lançando.

Na plataforma .NET não existe a cláusula throws na assinatura de métodos. Desta forma , você deve documentar explicitamente as exceções que esta lançando para que o usuário saiba. Parece que isto foi feito intencionalmente de forma a que se tenha um tratamento de erros centralizado. A plataforma .NET também não possui as Checked Excpetions que a linguagem Java Possui.

Na próxima parte do curso iremos tratar da depuração do código.

Referências:


José Carlos Macoratti