Desenvolvimento - C#
C# e Oracle
Neste artigo aborda o acesso a dados usando o Oracle 9i e C#. Embora seja bem simples, o acesso ao Oracle possui particularidades que devem ser levadas em consideração, principalmente por quem está habituado a trabalhar com SQL Server.
por Danielle MonteiroNeste meu primeiro artigo resolvi falar de um assunto que pode dar trabalho para muitos desenvolvedores, o uso de C#/ VB.net usando uma base Oracle 9i.
O Framework 2005 apesar de maravilhoso, não possui suporte nativo (com a mesma eficiência e eficácia do suporte ao SQL Server 2005) ao Oracle. É necessário destacar que para o desenvolvimento deste tipo de sistemas é preciso baixar um provider específico para este fim o ODP.NET (disponível no site da Oracle http://www.oracle.com/technology/tech/windows/odpnet/index.html, onde podemos ter também informações muito úteis!!!)
Com o provider instalado e o projeto iniciado, além das referências default para acesso aos dados (System.Data e System.Data.Common) é preciso adicionar a seguinte referência ao projeto: Oracle.DataAccess.dll . Sem ela nada funciona!
Porque eu estou falando tudo isso?
O motivo é simples, há algumas diferenças fundamentais entre o Oracle e o SQL Server na manipulação dos dados, principalmente quando os comandos estão armazenados em Packages ou Stored Procedures.
Como a intenção não é promover uma comparação entre o Oracle 9.i e o SQL Server 2005, incluirei aqui somente os códigos usados para a manipulação de dados vindos do Oracle.
Exemplificarei aqui a Consulta de Dados já que no Oracle um select que retorna uma lista de dados tem algumas particularidades. As outras operações não têm muitas mudanças, mas podem ser assunto de uma continuação deste artigo...
Vamos começar pelos scripts...
1 - Usarei para este exemplo uma tabela simples chamada tbCliente:
1º) Classe que faz acesso aos dados:
Para finalizar:
Enfim, espero que este artigo tenha muita utilidade! Qualquer dúvida, crítica ou sugestão sintam-se a vontade para entrar em contato comigo no email Dani@wbsoft.com.br.
Abraços!
O Framework 2005 apesar de maravilhoso, não possui suporte nativo (com a mesma eficiência e eficácia do suporte ao SQL Server 2005) ao Oracle. É necessário destacar que para o desenvolvimento deste tipo de sistemas é preciso baixar um provider específico para este fim o ODP.NET (disponível no site da Oracle http://www.oracle.com/technology/tech/windows/odpnet/index.html, onde podemos ter também informações muito úteis!!!)
Com o provider instalado e o projeto iniciado, além das referências default para acesso aos dados (System.Data e System.Data.Common) é preciso adicionar a seguinte referência ao projeto: Oracle.DataAccess.dll . Sem ela nada funciona!
Porque eu estou falando tudo isso?
O motivo é simples, há algumas diferenças fundamentais entre o Oracle e o SQL Server na manipulação dos dados, principalmente quando os comandos estão armazenados em Packages ou Stored Procedures.
Como a intenção não é promover uma comparação entre o Oracle 9.i e o SQL Server 2005, incluirei aqui somente os códigos usados para a manipulação de dados vindos do Oracle.
Exemplificarei aqui a Consulta de Dados já que no Oracle um select que retorna uma lista de dados tem algumas particularidades. As outras operações não têm muitas mudanças, mas podem ser assunto de uma continuação deste artigo...
Vamos começar pelos scripts...
1 - Usarei para este exemplo uma tabela simples chamada tbCliente:
Create Table tbCliente (ID NUMBER NULL, Nome VARCHAR2(100) NULL );2 - Incluir dados na tabela criada:
insert into tbCliente (ID, Nome) values (1, "Astrogildo") insert into tbCliente (ID, Nome) values (2, "Emengarda") insert into tbCliente (ID, Nome) values (3, "Rivadavia") insert into tbCliente (ID, Nome) values (4, "Elidieanildete")3 - A package que servirá como base para o exemplo é a seguinte:
create or replace package pckCliente is -- Public type declarations /*Para retornar dados é preciso ter um tipo REF CURSOR declarado na package, porque os dados do select serão retornados em um objeto que possua este tipo */ TYPE T_CURSOR IS REF CURSOR; -- Procedures /*É preciso ter um parâmetro de saída com o tipo T_Cursor, para que ele receba os dados.*/ PROCEDURE spr_Cliente(cCursorDados out T_CURSOR); end pckCliente ; create or replace package body pckCliente is /**************************************************************/ /**************************************************************/ /**************************************************************/ PROCEDURE spr_Cliente(cCursorDados out T_CURSOR) AS /* Criar uma variável do tipo T_Cursor.*/ V_CURSOR T_CURSOR; begin /* A variável V_Cursor receberá os dados da consulta.*/ open V_CURSOR for SELECT ID , Nome FROM tbCliente; /*Atribuir o valor da variável ao parâmetro de saída.*/ cCursorDados := v_cursor; exception /*Variáveis de Manipulação de Exceções: sqlcode = Variável que armazena o código de erro; sqlerrm = variável que armazena a mensagem de erro*/ when others then raise_application_error(-20999, " Erro na consulta de Clientes! (Código do Erro: " || sqlcode ||" // Descrição do Erro: " || sqlerrm || ")"); END spr_Cliente; /**************************************************************/ /**************************************************************/ /**************************************************************/ end pckCliente ;Com a tabela criada e preenchida e com a package criada vamos ao código C#. Atenção aos comentários!
1º) Classe que faz acesso aos dados:
using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Data.Common; //Declarar a referência para a dll de data types do oracle using Oracle.DataAccess.Types; //Declarar a referência para o client do oracle using Oracle.DataAccess.Client; namespace Data { public class Data { /// <summary> /// Esta rotina cria o objeto de conexão /// </summary> /// <returns>OracleConnection</returns> public OracleConnection GetConnection() { //String de Conexão string connection = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=dani)(PORT=1521))) (CONNECT_DATA=(SERVICE_NAME=xe))); User Id=system; Password=dani"; return new OracleConnection(connection); } /// <summary> /// Rotina que executa o comando /// <param name="pNomeCmd">Nome do comando que será executado</param> /// <param name="pParametros">parâmetros do comando</param> /// <returns>string</returns> /// </summary> /// public DataTable ExecutaComando() { //Criar um objeto Oracle Connection OracleConnection cn = new OracleConnection(); //Declarar um objeto Oracle Command OracleCommand dbCommand = cn.CreateCommand(); //Criar um objeto DataTable DataTable oDt = new DataTable(); //Atribuir à variável cn o Valor da função GetConnection cn = GetConnection(); //Informar o nome do comando que será executado //Como estamos executando uma package devemos colocar //O nome da package seguido por um ponto e o nome da procedure dbCommand.CommandText = "pckCliente.spr_Cliente"; //O tipo do comando é StoredProcedure dbCommand.CommandType = CommandType.StoredProcedure; //Criar o tratamento para try { //A conexão que será usada é a que foi declarada no início do código dbCommand.Connection = cn; // Adicionar os parametros //**Procure preservar o mesmo nome do parâmetro e a mesma ordem em //que ele está declarado na stored procedure** //Parâmetro de saída cCursorDados //Pontos importantes: //O tipo do parâmetro deve ser obrigatóriamente RefCursor //Informar sempre a direção do parâmetro: Input, Output , InputOutPut, ReturnValue dbCommand.Parameters.Add(new OracleParameter("cCursorDados", OracleDbType.RefCursor, ParameterDirection.Output)); //Criar um objeto Oracle Data Adapter OracleDataAdapter oDa = new OracleDataAdapter(dbCommand); //Preenchendo o DataTable oDa.Fill(oDt); //Resultado da Função return oDt; } catch (Exception ex) { if (cn.State == ConnectionState.Open) { cn.Close(); } dbCommand.Dispose(); cn.Dispose(); throw ex; } finally { if (cn.State == ConnectionState.Open) { cn.Close(); } dbCommand.Dispose(); cn.Dispose(); } } } }2º) Console que executa a rotina:
using System; using System.Collections.Generic; using System.Text; using System.Data; //Incluir a referência à classe Data using Data; namespace Artigo001_090108 { class Program { static void Main() { //Criar um objeto DataTable DataTable oDt = new DataTable(); //Criar um objeto do tipo Data Data.Data obj = new Data.Data(); //Preenchendo o DataTable oDt = obj.ExecutaComando(); Console.WriteLine("Resultado Esperado para a Execução da Package:"); //Fazendo o Loop nas linhas do DataTable foreach (DataRow linhas in oDt.Rows) { Console.WriteLine("ID: " + linhas["ID"].ToString() + " - Nome: " + linhas["Nome"].ToString()); Console.WriteLine(); } } } }3º) Resultado esperado:
Para finalizar:
- O grande segredo é que o retorno de um comando select deve estar sempre em um parâmetro de saída;
- O parâmetro de saída pode ser de diversos tipos, já que com o ODP.NET, teremos suporte a praticamente todos eles.
Enfim, espero que este artigo tenha muita utilidade! Qualquer dúvida, crítica ou sugestão sintam-se a vontade para entrar em contato comigo no email Dani@wbsoft.com.br.
Abraços!