Apostila C Sharp para Iniciantes

  • Published on
    06-Aug-2015

  • View
    100

  • Download
    5

DESCRIPTION

criação de aplicações em C# , aplicações C Sharp, banco

Transcript

Introdução bem básica sobre C# O C# é uma das linguagens que você pode usar na plataforma .NET além dela você pode usar também VB .NET e qualquer implementação que use o .NET Framework , mas vou me ater somente as duas mais conhecidas e que são distribuídas com o Visual Studio. Então veja bem , você primeiro escolhe qual linguagem vai usar , no nosso caso C# ou VB .NET , para na sequência criar os seus projetos na linguagem escolhida. Dessa forma você pode desenvolver aplicações Windows Forms usando C# ou VB .NET como pode também desenvolver aplicações para web , no caso ASP .NET , usando C# ou VB .NET. Muita gente pensa que ASP .NET é uma linguagem, mas não é , veja a seguir uma definição sobe ASP .NET da WikiPédia: ASP.NET é a plataforma da Microsoft para o desenvolvimento de aplicações Web e é o sucessor da tecnologia ASP. É um componente do IIS que permite através de uma linguagem de programação integrada na .NET Framework criar páginas dinâmicas. Não é nem uma linguagem de programação como VBScript, php, nem um servidor web como IIS, Apache. O ASP.NET é baseado no Framework .NET herdando todas as suas características, por isso, como qualquer aplicação .NET, as aplicações para essa plataforma podem ser escritas em várias linguagens, como C# e Visual Basic .NET. fonte: http://pt.wikipedia.org/wiki/ASP.NET Veja também meus artigos : Minha primeira página ASP.NET e ASP.NET evolução ou enganação Bem, mas meu assunto neste artigo é C#. Então C# é uma linguagem que você pode usar para criar aplicações Windows Forms ou aplicações Web (ASP .NET). Se você pretende usar C# como sua linguagem de programação não vai precisar gastar um centavo pois pode usar as seguintes ferramentas: 1- Visual C# 2008 Express Edition 2- SharpDevelop 2.2 Nota: É bom você saber que existe o projeto Mono que pretende ser uma implementação livre e multiplataforma do .NET. O objetivo desse projeto é criar um framework de desenvolvimento opensource que seja robusto, confiável, fácil e agradável de ser utilizado.(http://www.monoproject.com/Main_Page) Cada uma delas possui recursos diferentes sendo que a primeira parece ser mais fácil de usar mas cabe a você verificar e escolher qual deseja usar. Com as ferramentas indicadas desenvolver aplicações fica muito simples mas neste artigo eu vou mostrar alguns aspectos básicos da linguagem que você deve saber embora talvez nunca precise usar. Como já foi dito você pode criar programas usando C# e apenas um editor como o bloco de notas. Embora isso não seja lá muito produtivo você pode seguir este caminho se desejar. Neste caso você deverá seguir os seguintes passos: 1- Digitar o seu programa C# em um editor de textos como o Bloco de Notas ( NotePad++) salvando-o com um nome qualquer e uma extensão .cs; 2- Compilar o programa usando o compilador de linha de comando C# chamado csc.exe; 3- Executar o programa; Nota: Um Editor gratuito muito versátil é o NotePad++ que suporta várias linguagens de programação. Antes de executar o csc.exe você pode precisar rodar o arquivo de lote vcvars32.bat que esta localizado na pasta de instalação do Visual Studio. Na minha máquina o caminho é: C:\Arquivos de programas\Microsoft Visual Studio 9.0\VC\bin Um dos programas C# mais simples que você vai conseguir criar pode ser visto a seguir: using System; class MainClass { public static void Main() { Console.WriteLine("O programa C# mais simples que existe. "); } } Abaixo temos um exemplo de código gerado pelo SharpDevelop: Note que o programa inicia com uma chamada ao método Main(); A declaração de namespaces em C# é feita usando a palavra using; Um bloco de código C# é delimitado por colchetes "{" e "}" um para abrir e outro para fechar. Se você abrir e não fechar o bloco vai ocorrer um erro. Para evitar esquecer de fechar um bloco de código siga as seguintes regras:(se desejar...) 1. Digite o parêntesis de abertura e fechamento na mesma linha; {} 2. Então pressione ENTER duas vezes para abrir espaço entre os parêntesis; { } 3. Agora digite o seu código no interior do bloco envolvido pelos parêntesis; A linguagem C# é case sensitive, ou seja, faz diferença entre maiúsculas e minúsculas. Exemplos: Declaração descrição private string nomesuario; define uma variável string nomeusario; private string define uma variável string Nomeusuario; Nomeusuario que é diferente da variável nomeusuario; private string define uma variável string nomeUsuario; nomeUsuario que é diferente das duas variáveis declaradas anteriormente; private string define uma variável string NomeUsuario; NomeUsuario que é diferente das demais variáveis declaradas anteriormente; Além disso toda declaração deve possuir o sinal de ponto e vírgula (;) ao seu final. Abaixo temos um exemplo de uma instrução que irá gerar o erro a esquerda, e a instrução correta a direita: { { Console.WriteLine(“Hello Console.WriteLine(“Hello” ”) ); } } errado correto Se você não tomar cuidado com estes pequenos detalhes pode ficar quebrando a cabeça procurando erros que são na verdade erros de digitação. Para documentar o seu código você pode usar tags XML e um comentário sendo que o comentário XML é sempre adicionado após barras triplas, conforme exemplo abaixo: using System; namespace DocumentationCommentsExample { /// /// A documentation sample the short description goes here /// /// Where a longer description would go< /remarks> class ClassExample { /// /// A member variable /// private string m_str; /// /// A method example /// /// a new value to be saved< /param> /// the length of the string public int MethodExample( string val ) { m_str = val; return val.Length; } } } Abaixo segue uma lista das tags XML mais usadas na documentação.( Lembre-se que com XML você pode criar suas próprias tags) TAG PROPÓSITO de uso … Breve descrição de uma classe, método ou propriedade. … Descrição mais detalhada. ... Permite delinear parágrafos dentro da tag Permite usar marcadores para … formatar uma descrição. Os tipos de marcadores podem ser “bullet”, “number” e “table”. … Para disponibilizar um exemplo de como usar um método, propriedade ou outro membro da biblioteca. … … Para indicar que o texto incluído é código da aplicação. Para indicar que o texto incluído é código da aplicação. É usada para linhas de código que precisam ser separadas da descrição. membro ou campo. O compilador verifica se o membro realmente existe. … Para fazer a descrição de uma exceção. … Para documentar a acessibilidade. … um método. … Para documentar um valor e seu tipo retornado de um método. … Para descrever uma propriedade A linguagem C# possui uma coleção de palavras chaves ou reservadas que são usadas pela linguagem conforme abaixo: Abstract Byte Class Delegate Event Fixed If as case const do explicit float implicit base catch continue double extern for in bool char decimal else false foreach int break checked default enum finally goto interface Internal New Override Readonly Short Struct Try Unsafe Void is null params ref sizeof switch typeof ushort while lock object private return stackalloc this uint using . long operator protected sbyte static throw ulong virtual . namespace out public sealed string true unchecked volatile . Note que as palavras reservadas são todas em caixa baixa (minúsculas) dessa forma o compilador não vai reconhecer a instrução Return pois a instrução correta é return. Além disso C# contém duas categorias de tipos de dados embutidos: 1- Tipos por valor - consistem em duas categorias : Struts e Enumerations; 2- Tipos por referência - definidos por classes; Qual a principal diferença ? Em suma uma variável de valor ou Value-Type contém diretamente a informação e uma variável de referência (Reference-Type) contém uma referência a um endereço de memória onde esta a informação. Value-Type • Armazena diretamente o valor; • Cada copia da variável contém uma copia do valor; • Operações em uma variável não afetam a sua cópia; • São variáveis Value-Type: integer, double, float e struct; Reference-Type • • • • Armazena uma referencia ao valor; Duas variáveis Reference-Type podem possuir uma referencia a um mesmo objeto; Operações feitas em uma varíavel afetam a outra; Variáveis Reference-Type: string, array e classes; Tipos de variáveis: A seguir temos os tipos usado no C# com sua referência no .NET Framework: Tipo C# Tipo .NET Significado Framework bool byte sbyte char System.Boolean System.Byte System.SByte System.Char Um caractere Tipo numérico para cálculos financeiros Ponto flutuante de precisão dupla Ponto Flutuante de precisão simples Inteiro inteiro sem sinal Inteiro Longo inteiro longo sem sinal objeto Inteiro Short Um inteiro short sem sinal Representa valores true e false inteiro de 8-bit sem sinal decimal System.Decimal double System.Double float int uint long ulong object short ushort System.Single System.Int32 System.UInt32 System.Int64 System.UInt64 System.Object System.Int16 System.UInt16 string Uma sequencia de caracteres A seguinte tabela mostra os tipos de variáveis e os valores possíveis de se armazenar em cada uma delas. System.String Tipo C# Valores possíveis de se armazenar bool byte sbyte char Verdadeiro ou Falso 0 a 255 (8 bits) -128 a 127 (8 bits) Um caractere (16 bits) decimal ±1.0 × 10-28 a ±7.9 × 1028 (128 bits) double ±5.0 × 10-324 a ±1.7 × 10308 (64 bits) float int uint long ulong object short ushort string ±1.5 × 10-45 a ±3.4 × 1038 (32 bits) -2,147,483,648 a 2,147,483,647 (32 bits) 0 a 4,294,967,295 (32 bits) –9,223,372,036,854,775,808 9,223,372,036,854,775,807 (64 bits) 0 a 18,446,744,073,709,551,615 (64 bits) Qualquer tipo. -32,768 a 32,767 (16 bits) 0 a 65,535 (16 bits) Seqüência caractere) de caracteres (16 bits por a C# - Sintaxe e conceitos básicos Se você já iniciou a migração para o VB.NET e já esta familiarizado com os conceitos básicos de orientação a objetos você já tem meio caminho andado para aprender C#. Mas afinal por que você iria querer aprender C# agora ? Existem muitas razões que eu poderia citar mas a principal é que haverá uma grande demanda para desenvolvedores com conhecimento de C# da plataforma .NET. Se você esta começando agora e ler este artigo até o fim verá que C# é muito mais fácil do que parece.(Se você conhece Java esta em casa...) Declarando váriáveis Declarar variáveis em C# é simples , abaixo temos a diferentes formas de declarar variáveis em C# int a; double area = 0; int salario, imposto , soma; int contador = 10; string nome; string nomeCompleto = "Little John"; Estruturas de repetição ( Laços ) while int while { i i ( = < Resultado 0; while: i 5 ) 1 2 Console.WriteLine ( 3 ); 4 ++i; do laço 0 } repete 5 vezes e imprime o valor de i. for ) i Resultado do laço For: 0 int i = 0; 1 for ( int i = 0; i < 5; i++ 2 3 { 4 Console.WriteLine ( ); } do ... while int i = 0; do { Console.WriteLine ( i ); i++; } while ( i < 5 ); foreach string [] nomes = new string[] { "Macoratti", "Miriam"}; foreach ( string nome in nomes ) { Console.WriteLine ( nome ); } O laço Do/While é quase igual ao laço While. A única diferença é que o código dentro do laço será executado pelo menos uma vez pois a seguir é feita a verificação da condição. O laço - foreach - pode ser usado para iterar através de uma coleção como um array , ArrayList ,etc. A saida para o laço é : Macoratti Miriam Operadores Condicionais if ... else string nome = "Macoratti"; if ( nome == "Pedro" ) { Console.WriteLine( "Você esta no bloco 'if'" ); } else { Console.WriteLine( "Você esta no bloco 'else'" ); } Operador usado para testar condições lógicas e executar a porção de código baseado na condição. No exemplo se o nome definido for igual a 'Pedro' teremos: Você esta no bloco 'if' Se o nome definido não for igual a 'Pedro' , teremos: Você esta no bloco 'else' Controle de fluxo em laços break string [] nomes = new string[] { "Macoratti", "Miriam", "Pedro"}; foreach ( string nome in nomes ) { Console.WriteLine ( nome ); if ( nome == "Miriam" ) break; } O comando break é usado para a saída de laços ( while, for , switch, etc..) No exemplo ao lado quando o nome for igual a 'Miriam' haverá a saída do laço devido ao comando break; A saida será: Macoratti Miriam continue string [] nomes = new string[] { "Macoratti", "Miriam", "Pedro"}; foreach ( string nome in nomes ) { if ( nome == "Miriam" ) continue; Console.WriteLine ( nome ); } O comando continue também é usado em laços(while, for, etc.) quando em execução o comando continue irá mover a execução para o próxima iteração no laço sem executar as linhas de código depois de continue. No exemplo a saída será: Macoratti Pedro O comando Switch é uma boa opção se você tiver que escrever muitas condições if..else. No exemplo , dependendo do valor do item condicional o código do case apropriado será executado. A saída para o exemplo será: Valor de i é : 6 Note que usamos instruções break para sair do bloco. Sem isto o próximo bloco Case seria executado. switch int i = 6; switch { case ( i ) 5: Console.WriteLine( "Valor de i é : " + 5 ); break; case 6: Console.WriteLine( "Valor de i é : " + 6 ); break; case 4: Console.WriteLine( "Valor de i é : " + 4 ); break; default: Console.WriteLine( "Valor de i é : " + i ); break; } C# - ADO .NET para Iniciantes - I O que é ADO .NET ADO .NET é a nova tecnologia para acesso a dados da plataforma .NET estando integrada ao .NET Framework e oferecendo diversas classes que permitem realizar praticamente todas as tarefas relacionadas com o acesso e manutenção de dados. ADO .NET oferece suporte a uma variedade de opções para desenvolvimento de soluções com acesso a dados que permitem a comunicação com qualquer fonte de dados, desde os já conhecidos gerenciadores de banco de dados relacionais (SGBD) como : SQL Server, MySQL, FireBird, Oracle, Sybase, Access, XML, arquivos textos, etc. Os componentes considerados os pilares da ADO.NET são o DataSet e os provedores .NET que são um conjunto de componentes que incluem os objetos : • Connection - responsável por efetuar a conexão com o banco de dados • Command - responsável por executar comandos contra o banco de dados; • DataAdapter - é utilizado para preencher o objeto DataSet; Através da ADO.NET podemos acessar dados de três maneiras básicas: OLE DB , SQL e ODBC. Os provedores de dados ADO .NET são livrarias de classes que permitem uma maneira comum de interagir com uma fonte específica de dados. Cada livraria possui um prefixo que indica qual provedor ela suporta. Veja abaixo os principais provedores: Nome Provedor ODBC Provider do API Descrição prefixo Data Odbc Fonte de dados com uma interface ODBC interface. Geralmente usada para banco de dados antigos; Fonte de dados que expõe uma interface OleDb interface, ou seja: Access ou Excel; OleDb Provider Data OleDb Oracle Provider SQL Provider Data Oracle Para banco de dados Oracle; Data Sql Para interação com Microsoft SQL Server; o Nota: Também existem provedores fornecidos por terceiros para MySQL, PostGreeSQL, FireBird, etc. Cada objeto possui uma versão para cada uma das maneiras aqui mencionadas, assim temos os objetos : • OleDbConnection, OleDbCommand, OleDbDataReader, OleDataAdapter; • SqlConnection, SqlCommand, SqlDataReader, SqlDataAdapter; • OdbcConnection, OdbcCommand,etc. Nota: Temos também os provedores fornecidos por terceiros como o .NET Connector para o MySQL. Abaixo uma figura ilustrando isto: Existem duas maneiras básicas de você realizar a conexão com uma fonte de dados com ADO .NET: 1- ) Usando um DataSet Este modo é conhecido como modo desconectado. O objeto DataSet veio para substituir com vantagens o objeto recordset (ADO) e, guarda poucas similaridades com o objeto recordset. Enquanto o objeto recordset representa uma coleção de tabelas de dados O objeto DataSet representa uma cópia do banco de dados em memória. A classe DataSet é membro do namespace System.Data e representa o primeiro dos dois maiores componentes da arquitetura ADO.NET os outros membros seriam os provedores Data .NET. Podemos resumir os atributos do DataSet como segue: É baseado em XML • É um conjunto de dados em cache que não esta conectado ao banco de dados • É independente da fonte de dados • Pode armazenar dados em múltiplas tabelas que podem ser relacionadas • Armazena múltipla versões de dados para coluna e para cada linha em cada tabela O DataSet fornece as principais funcionalidades para criar aplicações para banco de dados desconectados , embora suporte também o modelo conectado através de leitores de dados (DataReader). • A classe DataSet é derivada da classe System.ComponentModel.MarshalByValueComponent da qual ela recebe a habilidade de ser serializada , incluída na caixa de ferramentas do VS.NET e visualmente desenhada em um descritor. Os principais métodos da classe DataSet são : Membro Coleções Relations Uma coleção de relações hospedadas em um objeto DataRelationCollection que liga tabelas através de chaves estrangeira Uma coleção de tabelas que armazena os dados atuais Descrição Tables Métodos AcceptChanges Clear Clone Copy Grava todas as alterações para o DataSet Remove todas as linhas de todas as tabelas Faz uma cópia da estrutura mas não os dados de um DataSet Faz uma cópia a estrutura e os dados de um DataSet GetChanges Retorna uma cópia do DataSet com apenas as colunas alteradas ou aquelas que coincidem com o filtro definido em DataRowState Retorna uma representação exm XML dos dados Retorna uma representação estrutura de um DataSet XML da GetXml GetXmlSchema HasChanges Retorna um valor indicando que existe mudanças pendentes InferXmlSchema Infere a estrutura de um DataSet baseada em um arquivo ou fluxo Merge ReadXml Mescla o DataSet com o provedor Carrega um esquema XML e dados para um DataSet ReadXmlSchema Carrega um esquem XML para um DataSet Reset WriteXML Reverte o DataSet ao seu estado original Escreve os dados e o esquema XML para um arquivo ou fluxo de dados WriteXmlSchema Escreve o esquema XML para um arquivo ou fluxo 2- Usando um DataReader Os objetos DataReader é uma das maneiras mais fáceis para ler os dados retornados pelos objetos Command . Eles permitem acessar e percorrer os registros no modo de somente leitura e somente para frente forward-only . O DataReader não oferece o acesso desconectado e não permite alterar ou atualizar a fonte de dados original sendo usado para obter rapidamente dados de apenas leitura. Apresenta poucos recursos mas seu desempenho é muito melhor do que o oferecido pelos DataSet. As propriedades e métodos mais usadas dos objetos DataReader são : 1. FieldCount - informa o número de colunas da linha de dados atual 2. IsClosed - Indica se o objeto DataReader esta fechado. 3. RecordsAffected - especifica o número de linhas alteradas , excluídas ou incluídas na execução de uma declaração SQL 4. Item (n) - obtêm o valor da n-ésima coluna no seu formato nativo. 5. Close - Método que fecha o objeto 6. GetName - Método que retorna o nome da n-ésima coluna. 7. Read - método que permite ao DataReader avançar para o próximo registro 8. IsDbNull - método que informa se a n-ésima coluna possui um valor nulo. Para criar um objeto DataReader usamos o método ExecuteReader de um objeto Command. O objeto DataTable Ao tratar com banco de dados não podemos deixar de pensar em tabelas e o objeto DataTable representa uma ou mais tabelas de dados em memória. Os objetos DataTable estão contidos no objeto DataSet e/ou DataView. Abaixo temos uma relação das principais propriedades do objeto DataTable: • Columns - representa as colunas da tabela através da coleção de objetos DataColumn (DataColumnCollection) • • • • • • • • Rows - representa as linhas da tabela através de uma coleção de objetos DataRow (DataRowCollection) PrimaryKey - representa a chave primária da tabela atraves dos objetos DataColumn TableName - define o nome do objeto DataTable via coleção DatatableCollection em um objeto DataSet AcceptChanges - Efetiva as alterações realizadas no DataTable no banco de dados. NewRow - gera um novo objeto DataRow que representa uma linha de dados Copy - copia os dados e a estrutura do DataTable. Clear - limpa os dados de um DataTable. RejectChanges - ignora as alterações feitas no DataTable. O objeto DataView O DataView tem a função de permitir a ligação dos dados de uma fonte de dados com a interface do usuário através do DataBinding . Através do DataView podemos filtrar, ordenar, pesquisar e navegar pelos dados oferecendo diversas visões de um mesmo conjunto de dados ao usuário. Usamos o DataView para mostrar uma visão dos dados contidos em um DataTable , com isto você pode ter vários DataViews ligados a um mesmo DataTable , sendo que cada um exibe um visão diferente dos dados. O objeto DataTable possui um DataView padrão que é acessado através da propriedade DefaultView. As principais propriedades do objeto DataView são : • • • • • • • • • RowFilter - retorna uma expressão usada para filtrar os dados a serem exibidos pelo DataView. RowStateFilter - Define a versão dos dados que serão exibidos pelo DataView. Oferece as seguintes opções : o CurrendRows - linhas de dados atuais (linhas não alteradas , novas) o Added - linhas de dados novas. o Deleted - Linha excluída pelo método Delete o None - Nenhuma linha o ModifiedCurrent - linhas de dados que foram modificadas - versão atual o OriginalRows - linhas originais o Unchanged - Linhas não modificadas o ModifiedOriginal - linhas de dados que foram modificadas - versão original Count - informa o número de linhas no DataView após a aplicação dos filtros : RowFilter e RowStateFilter Item - obtêm uma linha de dados de um tabela especificada. Sort - define a coluna que irão ordenar o DataView e o tipo da ordenação ( ASC - ascendente ou DESC descendente) Addnew - Inclui uma nova linha no DataView Table - Define qual o objeto DataTable de origem para o DataView Delete - exclui uma linha do DataView Find - Busca por uma linha no DataView C# - ADO .NET para Iniciantes - II As Classes e os Namespaces da ADO .NET O seis principais namespaces (espaços de nome) da ADO .NET são mostrados abaixo resumidamente : Namespaces Descrição System.Data É o principal espaço de nomes da ADO .NET e contém as classes usadas por todos os provedores; classes que representam tabelas, colunas, linhas e também a classe DataSet. Além disso possui diversas interfaces como IDbCommand, IDbConnection, e IDbDataAdapter que são usadas por todos os provedores gerenciados. System.Data.Commom Define as classes comuns usadas como classes base para os provedores de dados. Todos eles compartilham estas classes. Ex: DbConnection e DbDataAdapter. System.Data.OleDb Define classes que trabalham com fonte de dados OLE DB usando o provedor .NET OleDb. Define classes que trabalham com fonte de dados ODBC usando o provedor .NET Odbc. System.Data.Odbc System.Data.SqlClient Define classes que trabalham com fonte de dados SQL Server 7.0 ou superior. System.Data.SqlTypes Define classes que representam tipos de dados específicos para o SQL Server. A ADO .NET possui 3 tipos distintos de classes referenciadas como: • Disconnected - Classes que fornecem a estrutura básica para o framework ADO .NET. Ex: A classe DataTable. Os objetos desta classe são capazes de armazenar dados sem qualquer dependência de um provedor específico; • Shared - Classes que Formam as classes bases para os provedores de dados e são compartilhadas entre todos os provedores; • Data Providers - São classes que são usadas com diferentes tipos de fonte de dados para realizar operações de gerenciamento de dados em um banco de dados específico. Os provedores de dados contém objetos Connection, Command, DataAdatper e DataReader que foram apresentados na primeira parte deste artigo. Com ADO .NET você primeiro cria um objeto Connection e fornece ao mesmo informação sobre a string de conexão. A seguir você criar um objeto Command e fornece a ele detalhes da instrução SQL que deverá ser executada. Esta informações pode usar parâmetros. Se o objeto Command retornar um conjunto de registros e você decidir usá-lo deverá criar um objeto DataAdapter e preencher um objeto DataSet ou DataTable. Usando o objeto Connection Um objeto Connection cria uma ligação (ou conexão) com uma fonte de dados específica. Este objeto deve conter a informação necessária para se conectar a fonte de dados usando informações como o provedor, o caminho da base de dados, o usuário e a senha (se necessário). Esta informação esta contida na string de conexão. Esta informação também pode ser armazenada no arquivo web.config , em um arquivo texto, no registro do windows, etc. Cada tipo de provedor de dados possui um objeto connection específico, assim um provedor de dados que trabalha com uma fonte de dados SQL Server inclui uma classe SqlConnection que realiza este tipo de operação. Já um provedor que trabalha com uma fonte de dados OLE DB possui uma classe OleDbConnection. Obs: Podemos também efetuar a conexão com outros banco de dados como MySQL, FireBird, PostGreSQL , DB2, etc. Neste caso será necessário usar um conector apropriado geralmente fornecido pelo fabricante ou usar um provedor de dados ODBC(não muito recomendável). De forma geral podemos descrever as propriedades para uma classe Connection assim : Propriedade Descrição ConnectionString Contém informações pelo objeto Connection para efetuar a conexão com o banco de dados; DataBase Retorna o nome do banco de dados após a conexão ser aberta; Retorna o nome da instância do banco de dados usado pelo objeto Connection; Retorna o estado atual conexão: Valores possíveis : • Broken • Closed • Connecting • Executing • Fetching • Open da DataSource State A seguir temos o trecho de código genérico usado para efetuar a conexão com o SQL Server : using System.Data; using System.Data.SqlClient; //1-definição das informações para montar a string de conexão string Server = "localhost"; string Username = "usuario"; string Password = "senha"; string Database = "banco de dados"; //2-montagem da string de conexão string ConnectionString = "Data Source=" + Server + ";"; ConnectionString += "User ID=" + Username + ";"; ConnectionString += "Password=" + Password + ";"; ConnectionString += "Initial Catalog=" + Database; //3-cria uma instância do objeto Connection em memória SqlConnection SQLConnection = new SqlConnection(); try { //4- atribui a string de conexão e abre a conexão SQLConnection.ConnectionString = ConnectionString; SQLConnection.Open(); //realiza alguma operação ...... } catch (Exception Ex) { MessageBox.Show(Ex.Message); } Para a conexão com o SQL Server podemos também declarar e instanciar o objeto SqlConnection ao mesmo tempo conforme o código abaixo: SqlConnection conn = new SqlConnection("Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI"); Neste caso o objeto SqlConnection instanciado usa um construtor com um único argumento do tipo string , a famosa string de conexão. Veja a seguir sua descrição detalhada : Data Source Identifica o servidor e pode ser a máquina local (localhost), um dns ou um endereço IP. Initial Catalog O nome do banco de dados Integrated Security Defina para SSPI para fazer a conexão usando a autenticação do WIndows.(Usar Integrated Security é seguro somente quando você esta em uma máquina fora da rede) User ID Password Nome do usuário definido no SQL Server. Senha do usuário definida no SQL Server. Um exemplo de conexão com o meu servidor MAC/SQLEXPRESS usando o banco de dados Northwind.mdf com o usuário macoratti e senha 123456 seria: SqlConnection conn = new SqlConnection("Data Source=MAC/SQLEXPRESS;Initial Catalog=Northwind;User ID=macoratti;Password=123456"); A sequência de operações que ocorrem quando da abertura de uma conexão pode ser resumida assim: • • • • • Instancia um objeto SqlConnection ou OledbConnection; Abre a conexão; Passa a conexão para outro objeto ADO .NET(command); Realiza a operação no banco de dados(uma consulta); Fecha a conexão; Um exemplo completo bem simples pode ser visto a seguir: using System; using System.Data; using System.Data.SqlClient; /// /// Demonstra como trabalhar abrir uma conexão com SqlConnection /// class SqlConnectionDemo{ static void Main() { // 1. Instancia a conexão(objeto SqlConnection) SqlConnection conn = new SqlConnection("Data Source=.\\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=SSPI"); // // define um SqlDataReader nulo SqlDataReader dr = null; try { // 2. Abre a conexão conn.Open(); // 3. Passa conexão para o objeto command SqlCommand cmd = new SqlCommand("select * from Customers", conn); // // 4. Usa conexão // obtêm o resultado da consulta dr = cmd.ExecuteReader(); // imprime o codigo do cliente para cada registro while (dr.Read()) { Console.WriteLine(dr[0]); } } finally { // fecha o reader if (dr != null) { dr.Close(); } // 5. Fecha a conexão if (conn != null) { conn.Close(); } } } } O código usa um objeto SqlCommand o qual realiza uma consulta na tabela Customers. O resultado é retornado como um SqlDataReader e o loop While percorre e lê a primeira coluna de cada linha do conjunto de registros retornados que é a coluna CustomerID. (poderíamos ter obtido mais colunas como dr[1], dr[2], etc.) Nota: Podemos também obter os dados das colunas pelo nome dos campos : Ex: dr["CustomerID"]. Ao usar o objeto Connection você deve sempre ter o cuidado de fechá-lo caso contrário haverá impacto no desempenho da sua aplicação, por isso estou usando um bloco Try/Finally, onde o bloco Finally garante que a conexão será fechada pois sempre será executado. Note que tomamos a precaução de verificar se a conexão e o objeto DataReader eram nulos antes de fechá-los para evitar uma exceção. Este exemplo mostra como usar o SqlConnection com o objeto SqlDataReader o qual requer que a conexão seja fechada explicitamente. C# - ADO .NET para Iniciantes III - Command (SqlCommand) Falando um pouco objeto SqlCommand sobre o O objetivo desta aula é descrever o objeto SqlCommand e como você pode usá-lo para interagir com um banco de dados. Resumindo os objetivos são: • Conhecer o que é o objeto SqlCommand; • Aprender como usar o método ExecuteReader para consultar dados; • Aprender como usar o método ExecuteNonQuery para inserir ou excluir dados; • Aprender a usar o método ExecuteScalar para retornar um valor único; Veja na tabela a seguir um resumo para cada um dos métodos citados: Método ExecuteReader Descrição Executa a consulta e retorna um objeto SqlDataReader; ExecuteNonQuery Executa a consulta e não retorna nenhuma coleção. Usado para instruções INSERT, DELETE e UPDATE onde retorna o número de registros afetados. Ex: SqlCommand sqlComm = new SqlCommand("DELETE FROM Categories WHERE CategoryID=1", sqlConn); sqlComm.ExecuteNonQuery(); ExcecuteScalar Executa a consulta e retorna um único valor.(uma linha e uma coluna) Introdução Um objeto SqlCommand permite que você especifique qual tipo de interação você deseja realizar em um banco de dados: selecionar, incluir, modificar e excluir dados e pode ser usado para dar suporte em operações em um cenário de gerenciamento de dados no modelo desconectado mas irei focar nesta aula como usar o SqlCommand de forma simples e isolada. A classe SqlCommand é usada para representar uma instrução SQL ou stored procedure disparada com o objetivo de inserir, atualizar, excluir ou selecionar informações de uma fonte de dados. A sua posição na hierarquia de classes da plataforma .NET é dada a seguir: System.Object System.MarshalByRefObject System.ComponentModel.Component System.Data.Common.DbCommand System.Data.Odbc.OdbcCommand System.Data.OleDb.OleDbCommand System.Data.OracleClient.OracleCommand System.Data.SqlClient.SqlCommand System.Data.SqlServerCe.SqlCeCommand Para criar um objeto SqlCommand podemos usar um construtor criando uma instância da classe SqlCommand passando a string SQL que representa qual operação desejamos realizar contra o banco de dados e o objeto SqlConnection que deverá ter sido criado anteriormente contendo a conexão com a fonte de dados: SqlCommand cmd = new SqlCommand("select * from Clientes", conn); cmd - instância da classe SqlCommand • select * from clientes - instrução sql para selecionar todos os clientes da tabela Clientes; • conn - a conexão com o banco de dados; • Podemos então realizar as seguintes operações com o objeto SqlCommand: Nos exemplos abaixo irei usar uma tabela chamada Clientes com a seguinte estrutura: • id - int - primary Key • nome - varchar(50) • email - varchar(50) 1- Consultar dados Para consultar dados você usa uma instrução SQL SELECT para retornar um conjunto de dados para visualização. Para obter este resultado você pode usar o método ExecuteReader o qual retorna um objeto SqlDataReader da seguinte forma: // 1. Instancia um novo comando com uma consulta e uma conexão SqlCommand cmd = new SqlCommand("select * from Clientes", conn); // 2. Chama o método ExecuteReader para obter o resultado da consulta SqlDataReader dr = cmd.ExecuteReader(); 2- Incluir dados Para inserir registros em um banco de dados use o método ExecuteNonQuery do objeto SqlCommand : // prepara um comando SQL para incluir dados usando a instrução INSERT INTO string incluiSQL = @" insert into Clientes (Nome, Email) values ('Macoratti', 'macoratti@ig.com.br')"; // 1. Instancia um novo comando com uma consulta e uma conexão SqlCommand cmd = new SqlCommand(incluiSQL , conn); // 2. Chama o método ExecuteNonQuery para enviar o comando cmd.ExecuteNonQuery(); Aqui alteramos ligeiramente a forma de instanciar um objeto SqlCommand passando a variável incluiSQL como parâmetro. Um detalhe importante é que estamos incluindo valores para os campos Nome e Email mas a tabela possui um campo id que é a chave primária que não faz parte da instrução. Isto é devido ao fato da inclusão deste campo ser feita de forma automática pelo SQL Server. Se você tentar incluir um valor para o campo id no código irá obter uma exceção em tempo de execução. 3- Atualizar dados O método ExecuteNonQuery também é usado para atualização de dados: // prepara um comando SQL para incluir dados usando a instrução Update string atualizaSQL = @"update Clientes set Nome = 'Macoratti' where id = 1"; // 1.Instancia um novo comando com uma consulta sql SqlCommand cmd = new SqlCommand(atualizaSQL ); // 2. Define a propriedade Connection cmd.Connection = conn; // 3. Chama o método ExecuteNonQuery para enviar o comando cmd.ExecuteNonQuery(); Neste código usamos um construtor SqlCommand que possui somente um comando, logo em seguida nós atribuímos o objeto SqlConnection (conn) usando a propriedade Connection do objeto SqlCommand cmd; Com isso mostramos que podemos alterar o objeto Connection a qualquer tempo. 4- Excluir dados O método ExecuteNonQuery também é usado para excluir dados: // prepara um comando SQL para incluir dados usando a instrução DELETE string excluiSQL = @"delete from Clientes where id = 1"; // 1. Instantcia um novo comando SqlCommand cmd = new SqlCommand(); // 2. Define a propriedade CommandText cmd.CommandText = excluiSQL ; // 3. Define a propriedade Connection cmd.Connection = conn; // 4. Chama o método ExecuteNonQuery para enviar o comando cmd.ExecuteNonQuery(); Neste exemplo usamos o construtor SqlCommand sem parâmetros mas logo em seguida definimos explicitamente as propriedades CommandText e Connection do objeto SqlCommand, cmd. Com isso mostramos que podemos alterar o objeto Connection e Command a qualquer tempo. 5- Obtendo valores Às vezes tudo o que você precisa do banco de dados é um valor único que pode ser o resultado de uma contagem, soma, média, ou outro valor agregado. Usar um ExecuteReader e calcular o resultado no seu código não é a forma mais eficiente de fazer isso. A melhora maneira é deixar o banco de dados realizar a operação e retornar apenas um valor único como resultado. Para isso usamos o método ExecuteScalar: // 1. Instantcia um novo comando SqlCommand cmd = new SqlCommand("select count(*) from Clientes", conn); // 2. Chama o método ExecuteScalar para enviar o comando int count = (int)cmd.ExecuteScalar(); A consulta no construtor SqlCommand obtém a contagem de todos os registros a partir da tabela Clientes e irá retornar somente o valor da contagem. O método ExecuteScalar retorna um valor do tipo Object, temos que efetuar uma coerção forçada (casting) para converter o valor para um int. using System.Data.SqlClient; namespace adonetCshp_3 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { string connetionString = null; SqlConnection cnn = default(SqlConnection); SqlCommand cmd = default(SqlCommand); string sql = null; connetionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=Cadastro;Integrated Security=SSPI"; sql = "Select Count(*) from clientes"; cnn = new SqlConnection(connetionString); try { cnn.Open(); cmd = new SqlCommand(sql, cnn); Int32 contador = Convert.ToInt32(cmd.ExecuteScalar()); cmd.Dispose(); cnn.Close(); MessageBox.Show(" No. de linhas " + contador ); } catch (Exception ex) { MessageBox.Show("Não foi possível abrir a conexão com o banco de dados ! " + ex.Message.ToString()); } } } } A seguir um exemplo realizando as operações CRUD na tabela Clientes do banco de dados Cadastro.mdf: using System; using System.Data; using System.Data.SqlClient; class ExecutaInsertUpdateDelete { public static void exibirRegistro(SqlCommand comando, string ID) { comando.CommandText ="SELECT codigo, nome FROM Clientes WHERE codigo = '" + ID + "'"; SqlDataReader dr = comando.ExecuteReader(); while (dr.Read()) { listBox1.Items.Add("dr[\" codigo\"] = " + dr["codigo"]); listBox1.Items.Add("dr[\" nome\"] = " + dr["Nome"]); } dr.Close(); } public static void Main() { connetionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=Cadastro;Integrated Security=SSPI"; SqlConnection conexaoSql =new SqlConnection(connetionString) ; SqlCommand comando = conexaoSql.CreateCommand(); comando.CommandText ="INSERT INTO Clientes (codigo, nome) VALUES (" + " 19, 'Macoratti')"; conexaoSql.Open(); int numeroLinhasAfetadas = comando.ExecuteNonQuery(); l listBox1.Items.Add("Numero de linhas afetadas = " + numeroLinhasAfetadas); exibirRegistro(comando, "9"); comando.CommandText = "UPDATE Clientes SET Nome = 'Novo' WHERE codigo = 19"; numeroLinhasAfetadas = comando.ExecuteNonQuery(); listBox1.Items.Add("Numero de linhas atualizadas = " + numeroLinhasAfetadas); exibirRegistro(comando, "9"); comando.CommandText ="DELETE FROM Clientes WHERE codigo = 19"; numeroLinhasAfetadas = comando.ExecuteNonQuery(); listBox1.Items.Add("Numero de linhas deletadas = " + numeroLinhasAfetadas); conexaoSql.Close(); } } Para encerrar eu gostaria de falar sobre o bloco using: A instrução using declara o início de um bloco Using e opcionalmente adquire os recursos do sistema que o bloco controla. Um bloco Using garante a liberação de um ou mais dos tais recursos quando seu código estiver finalizado com eles. Isso torna-os disponíveis para uso por outros códigos. As Classes SqlConnection e SqlCommand implementam a interface IDisposable e isto significa que eles podem usar recursos não gerenciados e liberar tais recursos é trabalho do desenvolvedor, de forma que depois de usar estas classes temos que chamar o método Dispose(). Se ocorrer uma exeção no acesso ao banco de dados temos que ter certeza que o Dispose() foi chamado , este é um motivo para usar a palavra reservada Using. Obs: Recursos gerenciados são descartados pela coletor de lixo .NET Framework (GC) sem qualquer codificação extra de sua parte. Você não precisa de um bloco Using para recursos gerenciados. Veja abaixo um exemplo de bloco Using para criar uma tabela em um banco de dados; a string de conexão esta sendo obtida a partir do arquivo de configuração using (SqlConnection con = new SqlConnection(Macoratti.Properties.Settings.Defaul t.MacorattiConnectionString)) { con.Open(); try { using (SqlCommand command = new SqlCommand("CREATE TABLE Macoratti (Codigo INT, Nome TEXT, Endereco TEXT)", con)) { command.ExecuteNonQuery(); } } catch { Console.WriteLine("Tabela não pode ser criada"); } } Outro exemplo usando Using e comparando com a sintaxe tradicional sem usar Using: using (SqlConnection cn = new SqlConnection(connection String)) { using (SqlCommand cm = new SqlCommand(commandS tring, cn)) { cn.Open(); cm.ExecuteNonQuery(); } } SqlConnection cn = null; SqlCommand cm = null; try { cn = new SqlConnection(connection String); cm = new SqlCommand(commandS tring, cn); cn.Open(); cm.ExecuteNonQuery(); } finally { if (null != cm); cm.Dispose(); if (null != cn) cn.Dispose(); } Os dois trechos de código acima são equivalentes. C# - ADO .NET para iniciantes IV - DataReader (SqlDataReader) O objeto DataReader da ADO .NET pertence ao namespace System.Data e apresenta as seguintes especificidades: • Acessa as informações em uma fonte de dados de forma mais rápida; • É usado somente para exibir rapidamente as informações de uma base de dados; • Seus dados obtidos são somente leitura e é possível somente caminhar para frente na navegação pelos dados; • Ele exige que a conexão esteja aberta enquanto estiver sendo usado e reflete o estado mais atualizado possível dos dados; Você vai encontrar na leitura técnica a designação de que o um DataReader é forward-only (somente para frente) e read-only (somente-leitura). O resultado gerado por um DataReader é retornado pela execução da consulta e é armazenada no buffer da rede no cliente até que seja requisitado através do método Read(). Resumindo as funcionalidades do DataReader: - É um objeto somente leitura e para frente, ou seja, não você não pode navegar aleatoriamente; - Opera conectado ao banco, assim, enquanto estivermos utilizando-o para obter os dados do banco, estaremos com a conexão do banco aberta; - Opera apenas com uma tabela por vez; você deve configurar a string SQL para a primeira tabela, conectar no banco, coletar suas informações e desconectar do banco. Para a segunda tabela você deverá repetir o processo; Nota: A conexão utilizada pelo DataReader deve ser aberta e fechada manualmente.(exceto quando você informa que ela deverá ser fechada de forma automática usando a enumeração CommandBehavior.CloseConnection) Você deve usar um DataReader em sua aplicação quando: • Você precisar trabalhar somente com uma tabela de dados por vez • você não precisar usar cache de dados • você precisar somente exibir os dados de uma tabela • você precisar acessar de forma rápida e de uma vez os dados de uma forma somente-leitura e somente-parafrente • você precisar processar uma quantidade de dados muito grande para caber na memória Nota: O DataAdapter usa o DataReader par preencher o DataSet. Desta forma , o desempenho ganho pela utilização do DataReader é que você salva na memória os dados que o DataSet irá consumir. O roteiro básico para utilização de um objeto DataReader é o seguinte: • criar uma instância de um objeto Command; • criar um objeto DataReader(); • chamar o método ExecuteReader do objeto Command(); • Obter o retorno da consulta usando o método Read(); Abaixo temos um exemplo bem básico do código usando SqlDataReader: using System.Data; using System.Data.SqlClient; string connString = "Data Source=server;Initial Catalog=database;Persist Security Info=True;User ID=sa;Password=xxx" SqlConnection adoConn = new SqlConnection(connString); adoConn.Open(); // novo command string sql = "SELECT * FROM Tabela"; SqlCommand adoCmd = new adoConn); SqlCommand(sql, SqlDataReader adoDR = adoCmd.ExecuteReader(); if (adoDR.HasRows) { while (adoDR.Read()) { Response.Write(adoDR["0"].ToString()); } } adoDR.Close(); adoDR.Dispose(); adoCmd.Dispose(); adoConn.Close(); adoConn.Dispose(); Observe as linhas em negrito onde temos: 1-) A criação de um objeto SqlCommand usando uma instrução SQL e a conexão SqlCommand adoCmd = new SqlCommand(sql, adoConn); 2-) A criação de um objeto SqlDataReader e utilização do método ExecuteReader() do objeto SqlCommand; SqlDataReader adoDR = adoCmd.ExecuteReader(); 3-) Utilização do método Read() para ler o resultado while (adoDR.Read()) Veja a seguir outra forma de obter o mesmo resultado: using System.Data.SqlClient; public void exibirDados() { string consulta = "SELECT * FROM Tabela"; SqlConnection conexao = new SqlConnection("conString"); SqlCommand comando = new SqlCommand(consulta, conexao); SqlDataReader dr = null; try { conexao.Open(); dr = comando.ExecuteReader(); while (dr.Read()) { Console.WriteLine(dr.GetString(1)); } } catch{ Console.WriteLine("Erro."); } finally { dr.Close(); conexao.Close(); } } Observe que abrimos uma conexão com a fonte de dados e após executar a consulta usando o método ExecuteReader() atribuímos o resultado ao objeto SqlDataReader dr. Para exibir o resultado usamos um laço While onde percorremos o SqlDataReader usando o método Read(), este método avança sempre para o próximo registro e retorna True enquanto existir um registro a ser lido. Para ler os valores retornados podemos usar o nome da coluna, o seu índice ou os métodos Get do SqlDataReader: dr["nome_da_Coluna"] • dr[0] • dr.getString(0) • O objeto SqlDataReader possui alguns métodos para obter os dados das colunas como: GetString(), GetValue(), getDateTime(), GetDouble(), GetChar(), GetGuid(), GetInt16(), GetInt32(), etc.. Cada um destes métodos usa um valor inteiro como índice baseado em zero e representa a coluna a ser obtida. Assim dr.GetString(0) retorna o valor da primeira coluna. Para detalhes veja o link: http://msdn.microsoft.com/enus/library/system.data.sqlclient.sqldatareader _members.aspx No primeiro exemplo antes de iniciarmos o laço e a leitura do DataReader usamos o método HasRows que é usado para verificar se existem linhas no DataReader, se existir ele retorna True, se não retorna False e neste caso nem iniciaremos a leitura do mesmo. O enumerador CommandBehavior possui o item CloseConnection() que pode ser usado com o método ExecuteReader do objeto SqlCommand() da seguinte forma: dr = comando.ExecuteReader(CommandBehavio r.CloseConnection) neste caso estamos passando o CommandBehavior.CloseConnection() como parâmetro para o objeto ExecuteReader e com isso não temos a necessidade de fechar a conexão explicitamente com a fonte de dados, pois ao percorrer os dados o próprio DataReader irá fechar a conexão quando o método Close() do DataReader for chamado. Veja um exemplo usando este recurso: using System.Data.SqlClient; public void exibirDados(){ SqlConnection conexao = new SqlConnection("connString"); SqlCommand comando = new SqlCommand("SELECT * FROM TABELA", conexao); SqlDataReader dr=null; try { conexao.Open(); dr = comando.ExecuteReader(CommandBehavio r.CloseConnection); while (dr.Read()) { Console.WriteLine(dr.GetString(1)); } } catch (Exception ex) { Console.WriteLine("Erro."); } finally { dr.Close(); } } Observe que neste caso não fechamos a conexão explicitamente com o banco de dados. Para verificar se a conexão ainda esta aberta podemos verificar o seu estado usando o código a seguir: if (conexao.State != ConnectionState.Closed) conexao.Close(); Exemplo DataReader prático usando No exemplo a seguir vamos criar uma aplicação C# com uma interface bem simples que permite aos usuários procurar pelo nome dos produtos na tabela Products do banco de dados Northwind.mdf. Este exemplo usará o seguintes recursos: • Visual C# 2008 Express Edition - para criar o projeto da aplicação C#; • SQL Server 2005 Express Edition - para gerenciar o banco de dados Northwind.mdf; • Criação de consultas parametrizadas - definindo parâmetros na instrução SQL; • Utilização do método ExecuteReader executando a instrução SQL que o objeto Command representa e retornando o objeto DataReader; Abra o Visual C# Express Edition e crie um novo projeto do tipo Windows Application com o nome uDataReader; A seguir no formulário padrão inclua os controles : Label, Button - btnProcurar , ListBox - lbDados e TextBox - txtcriterio conforme o leiaute abaixo: Agora defina o namespace : using System.Data.SqlClient; No evento Click do botão de comando Procurar insira o seguinte código: private void btnProcurar_Click(object sender, EventArgs e) { //define os objetos DataReader, Connection e Command SqlDataReader sqldr = null; SqlConnection con = null; SqlCommand cmd = null; try { // Abre a conexão com o banco de dados Northwind no SQL Server 2005 Express // .\SQLExpress é o nome default do servidor // initial Catalog - indica o banco de dados // String usando Windows Authentication (Trusted Connection): string ConnectionString = "Data Source=.\\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=SSPI"; con = new SqlConnection(ConnectionString); con.Open(); // define um comando para selecionar os produtos e preços da tabela products string CommandText = "SELECT ProductName,UnitPrice " + "FROM Products " + "WHERE (ProductName LIKE @criterio)"; //associa comando a conexão cmd = new SqlCommand(CommandText); cmd.Connection = con; // Define o parâmetro @criterio e seu tipo de dados cmd.Parameters.Add( new SqlParameter( "@criterio", // o nome do parametro System.Data.SqlDbType.NVarChar, // o tipo de dado SqlDbType 40, // o tamanho do parametro "ProductName")); // o nome da coluna na tabela aplica // Preenche o valor do com o texto // na caixa de texto : a qual se parâmetro informado txtcriterio cmd.Parameters["@criterio"].Value = txtcriterio.Text+"%"; // executa a consulta sqldr = cmd.ExecuteReader(); lbDados.Items.Clear(); // preenche o listBox com os valores retornados // usa o método read() para percorrer o datareader while (sqldr.Read()) { lbDados.Items.Add(sqldr["ProductName"].ToS tring() + " - " + sqldr["UnitPrice"].ToString()); } } catch (Exception ex) { // exibe mensagem de erro MessageBox.Show(ex.Message); } finally { // fecha o data reader e a conexão if (sqldr != null) sqldr.Close(); if (con.State ConnectionState.Open) con.Close(); } } == Note que estamos usando o parâmetro @criterio para receber o valor informado na caixa de texto na instrução de comando SQL : SELECT Products ProductName,UnitPrice FROM WHERE (ProductName LIKE @criterio)"; Ao atribuir o valor ao parâmetros incluímos o caractere % ao final do valor digitado: cmd.Parameters["@criterio"].Value txtcriterio.Text+"%"; = Após executar o comando via método ExecuteReader() percorremos o DataReader com o método Read() e obtemos os valores usando a sintaxe: sqldr["ProductName"].ToString() + " - " + sqldr["UnitPrice"].ToString() O resultado para a letra C pode ser visto abaixo: Usando uma Stored Procedure Podemos também gerar um DataReader executando uma stored procedure. Supondo que você tenha uma stored procedure criada no banco de dados com o nome listaClientes que obtêm os clientes para um determinado id. O código usado para definir o comando e passar o parâmetro pode ser escrito assim: 1 SqlCommand storedProcCommand = new SqlCommand ("listaClientes", con); 2 storedProcCommand.CommandType = CommandType.StoredProcedure; 3 storedProcCommand.Parameters.Add("@ID",clien teID); 4 SqlDataReader reader = storedProcCommand.ExecuteReader(); 5 while (reader.Read()) {//} - Na primeira linha construímos o objeto SqlCommand com o nome da stored procedure usando a conexão com o banco de dados; - Na linha 2 o objeto Sqlcommand define que estará executando uma stored procedure; - Na linha 3 incluímos o parâmetro no objeto SqlCommand. Observe o uso do símbolo @ usado para identificar um parâmetro no SQL Server. - Na linha 4 usamos o método ExecuteReader() para executar a stored procedure e retornar um DataReader; - Na linha 5 iniciamos a leitura do DataReader; Lembrete: Um DataReader é sempre mais rápido que um DataSet ??? A resposta é : DEPENDE... A vantagem do DataReader e não ter que carregar todo o conteúdo da tabela em memória, e retornar os registros à medida que são disponibilizados pelo banco de dados; enquanto que o DataSet aguarda o fim da execução da consulta para prosseguir a execução. Quando você usa um DataSet, todos os registros retornados são carregados na memória, para depois serem processados. O DataReader carrega na memória apenas o registro atual. Por isso, não é possível acessar registros anteriores.(Ele é forward-only lembra-se ?) Então, se você usar o DataReader para ler TODOS os registros do banco de dados e carregá-los na memória esta fazendo com que o seu DataReader se comporte como um DataSet. Ora !! neste caso é melhor um DataSet pois exige menos código para ser tratado. C# - ADO .NET para iniciantes IV - SqlDataAdapter e DataSet Esta chegando agora ??? Então acompanhe as dois primeiros artigos: • C#- ADO .NET para iniciantes - I • C#- ADO .NET para iniciantes - II • C#- ADO .NET para iniciantes - III • C#- ADO .NET para iniciantes - IV Se você já conhece VB .NET e esta querendo a aprender C# sugiro que você leia o meu artigo: • VB.NET e C# - Guia rápido de referência comparativa O material necessário para acompanhar o curso é: (Irei utilizar o Visual C# 2008 Express Edition) 1- Visual C# 2008 Express Edition (vou dar preferência ao Visual C#) 2- SharpDevelop 2.2 (opcional) 3- SQL Server 2005 Express Edition No artigo anterior escrevemos sobre o DataReader, e, embora o objeto DataReader seja rápido e muito simples de usar, em muitas situações, teremos que efetuar operações em nossos dados que vão além da exibição e movimentação somente para frente; muitas vezes teremos que realizar operações de inclusão, alteração, exclusão, etc., e, neste caso as classes DataSet e SqlDataAdapter são as mais indicadas para serem usadas. A classe DataSet O DataSet representa um conjunto de dados em memória retornados de uma fonte de dados e consiste de uma coleção de objeto DataTable que você pode inter-relacionar usando os objetos DataRelations. Você também pode forçar a integridade dos dados em um DataSet usando os objetos UniqueConstraints e ForeignKeyConstraints. Um DataSet é essencialmente um banco de dados em memória, contendo múltiplas tabelas, constraints, consultas, ordenações e a habilidade de persistir o seu estado em um arquivo XML. Você pode usar um SqlDataAdapter para preencher um DataSet com linhas de uma consulta feita em um banco de dados SQL Server. (Se acessar um banco de dados Access você usa um objeto OledbDataAdapter). Uma vez populadas você pode realizar alterações no DataSet, incluindo e excluindo linhas (rows), efetuando ordenações, etc, e então usar o objeto SqlDataAdpater novamente para refletir estas alterações no banco de dados original usando um comando SQL apropriado como UPDATE, DELETE, INSERT. Os dados estão contidos essencialmente no objeto DataTable mas é a coleção DataRelationCollection que permite que você a hierarquia da tabela. As tabelas estão contidas na coleção DataTableCollection que é acessada através da propriedade Tables. Lembre-se que ao usar um DataSet você esta trabalhando com uma cópia dos dados em memória e por isso qualquer atualização feita nos dados tem que ser refletida na fonte de dados de origem, de outra forma , se você não atualizar os dados originais com as alterações a fonte de dados não será atualizada. Os dados internos contidos em um DataSet são mantidos no formato XML e a estrutura do DataSet é definida pelo XSD (XML Schema Definition Language), ou seja, XML e DataSet estão intimamente ligados. A principal característica do DataSet é totalmente desconectado, você pode usar um DataSet para armazenar dados de um banco de dados e pode também mover os dados de um DataSet para um banco de dados, mas o próprio DataSet não faz conexão alguma com o banco de dados, ele nem mesmo tem um objeto para realizar tal conexão . Resumindo as funcionalidades do DataSet: - Funciona como um cache in-memory, ou seja, você terá as tabelas disponíveis para uso, podendo fazer acesso aleatório aos registros, inserir, alterar e deletar registros da tabela; - Opera desconectado do banco, assim , você trabalha com os registros sem usar uma conexão do banco de dados; - Opera com n tabelas por vez, e permite a possibilidade de relacionamento entre as mesmas além de funcionalidades como ordenação, filtragem, etc. Nota: A conexão utilizada pelo DataSet não necessita ser aberta e/ou fechada manualmente. Ao chamar o método Fill do DataAdapter a conexão é aberta, são coletados os dados solicitados e a conexão é fechada. (No caso do DataReader você tem que abrir e fechar) A classe SqlDataAdapter A classe SqlDataAdapter serve como uma ponte entre o DataSet e o banco de dados SQL Server para retornar e salvar dados. O SqlDataAdapter fornece esta ponte da seguinte forma: 1. O método Fill que altera os dados no DataSet para coincidir com os dados da fonte de dados; Quando o método Fill é executado ele cria as colunas e tabelas necessárias para os dados retornados se eles não existirem; a informação da chave primária não é incluída a menos que a propriedade MissingSchemaAction for definida para AddWithKey. 2. O método Update o qual altera os dados na fonte de dados para coincidir com os dados do DataSet usando o comando T-SQL apropriado contra a fonte de dados. A atualização é feita da seguinte forma: para cada linha inserida, modificada e deletada o método Update determina o tipo de alteração que foi realizada (Insert, Update ou Delete) e dependendo do tipo de alteração, o comando Insert, Update ou Delete é executado para propagar a linha modificada para a fonte de dados. De forma geral em uma implementação com mais de uma camada os passos para criar e atualizar um DataSet e em seguida atualizar os dados originais são: 1. Construir e preencher cada DataTable no DataSet com os dados da fonte de dados usando um objeto DataAdapter; 2. Alterar os dados nos objetos DataTable individuais pela inclusão, atualização ou exclusão de objetos DataRow; 3. Invocar o método GetChanges para criar um segundo DataSet que representa somente as alterações feitas; 4. Chamar o método Update do DataAdapter passando o segundo DataSet como um argumento; 5. Invocar o método Merge para mesclar as alterações a partir do segundo DataSet no primeiro; 6. Invocar o método AcceptChanges no DataSet ou invocar o método RejectChanges para cancelar as alterações; Criando um DataSet Todos as classes relacionadas como DataSet, DataAdapter, DataTable, DataRow etc estão disponíveis no namespace System.Data. A primeira coisa a fazer é definir o namespace que pode ser feito da seguinte forma: Em um arquivo Em uma página ASP .NET C#: System.Data; Para criar um objeto DataSet você usa a seguinte sintaxe: DataSet = new DataSet(); DataSet dsClientes = new DataSet(); Observe que o construtor DataSet não requer nenhum parâmetro, porém existe um construtor sobrecarregado que aceita uma string para o nome do DataSet o qual é usado se você deseja serializar os dados para o formato XML. Criando um SqlDataAdater Um SqlDataAdapter trata os comandos SQL e o objeto Connection para leitura e escrita de dados. Para inicializar um SqlDataAdaptar informamos um comando SQL e um objeto Connection que definia conexão com a fonte de dados: SqlDataAdapter daClientes = new SqlDataAdapter("Select codigo, Nome from Clientes", conexaoBD); No código acima criamos um novo SqlDataAdpater , daClientes onde o comando SQL Select especifica que iremos ler os dados para o DataSet e o objeto Connection , conexaoBD, que deverá já ter sido iniciado, mas não aberto. É responsabilidade do SqlDataAdpater abrir e fechar a conexão durante a chamada dos métodos Fill e Update. Para usar comandos SQL para incluir, atualizar e deletar temos duas maneiras distintas: • Usando as propriedades da classe SqlDataAdapter; • Usando o SqlCommandBuilder; O objeto SqlDataAdapter não gera automaticamente comandos Transact-SQL necessários para ajustar as alterações feitas a um DataSet associado com uma instância do SQL Server. Você pode , no entanto, criar um objeto SqlCommandBuilder para gerar automaticamente estes comandos para atualizações em uma tabela única . Veja abaixo um exemplo : SqlCommandBuilder cmdBldr = new SqlCommandBuilder(daClientes); O comando SqlCommandBuilder é instanciado usando como parâmetro a instância do SqlDataAdatper, no caso daClientes, dessa forma o SqlCommandBuilder irá ler os comandos SQL e atribuir os novos comandos as propriedades Insert, Update e Delete do SqlDataAdapter. o SqlCommandBuilder tem a limitação de gerar os comandos apenas para uma única tabela, se você precisar trabalhar com mais de uma tabela ou usar um Join terá que usar as propriedades da classe SqlDataAdapter. Preenchendo um DataSet Depois de criar instâncias de um DataSet e de um SqlDataAdpater você precisa preencher o DataSet usando o método Fill do SqlDataAdapter: daClientes.Fill(dsClientes, "Clientes"); O método Fill , usa dois parâmetros : • um DataSet - O DataSet precisa ser instanciado antes você tentar preenchê-lo com dados; • o nome de uma tabela - A tabela que será criada no DataSet. Você pode usar qualquer nome. Nota: O método Fill possui uma sobrecarga que usa somente o DataSet; neste caso a tabela criada terá um nome padrão de "table1" para a primeira tabela. Exemplos de utilização de um DataSet Recursos usados nos exemplos a seguir: • banco de dados Northwind.mdf do SQL Server 2005 Express Edition ; • conexão definida no meu Servidor SQL Server MAC\SQLEXPRESS (para adaptar o exemplo para o seu caso mude a string de conexão); • Visual C# 2008 Express Edition; 1- Usando um DataSet com SqlDataAdapter para selecionar dados no SQL Server Neste exemplo estamos apenas acessando o SQL Server 2005 e selecionando dados da tabela Products. Como não estamos alterando os dados não precisamos usar o objeto SqlCommandBuilder para preparar o DataSet para realizar tais operações. - Crie um novo projeto no Visual C# com o nome uDataSet1 do tipo Windows Forms Application ; - No formulário padrão form1.cs inclua um controle DataGridView - gdvProdutos e um controle Button - btnPreencheGrid ; - Defina o namespace System.Data.SqlClient - Declare as variáveis objetos que serão usadas no projeto: //define os objetos SqlConnection, DataSet //SqlDataAdapter e o nome da tabela private SqlConnection conn; private SqlDataAdapter daProdutos; private DataSet dsProdutos; private const string tabela = "Produtos"; - Inclua o seguinte código no evento Click do controle Button: private void btnPreencheGrid_Click(object sender, EventArgs e) { //chama a rotina para iniciar o dataset IniciaDados(); //exibe o dataset no controle datagridview dgvProdutos dgvProdutos.DataSource = dsProdutos; dgvProdutos.DataMember = tabela; } - A rotina IniciaDados() possui o seguinte código: // definição dos objetos dataset, sqldataadapter e sqlcommandbuilder public void IniciaDados() { try { //instancia uma nova conexão usando a string de conexão //com o banco de dados Northwind do SQL Server 2005 Express conn = new SqlConnection("Server=MAC\\SQLEXPRESS;DataBas e=Northwind;Integrated Security=SSPI"); // 1. instancia um novo DataSet dsProdutos = new DataSet(); // 2. inicia o SqlDataAdapte passando o comando SQL para selecionar codigo e nome // do produto e a conexão com o banco de dados daProdutos = new SqlDataAdapter("Select ProductID, ProductName from Products", conn); // 3. preenche o dataset daProdutos.Fill(dsProdutos, tabela); } catch(Exception ex) { //se houver erro exibe a mensagem MessageBox.Show(ex.Message); } } O resultado obtido pode ser visto na figura abaixo: 2- Usando um DataSet com SqlDataAdapter para incluir, alterar e excluir dados no SQL Server Vamos usar o exemplo anterior e incluir no formulário mais 3 botões de comandos para incluir, alterar e excluir dados da tabela Products; Incluir btnIncluir Alterar btnAlterar ExcluirbtnExcluir Vamos definir a variável do codigo como do tipo String que irá armazenar o código do produto. private String codigo = ""; A seguir temos o código do botão - Listar Dados que após obter a lista de produtos habilita os botões de comando: private void btnPreencheGrid_Click(object sender, EventArgs e) { IniciaDados(); //exibe o dataset no controle datagridview dgvProdutos dgvProdutos.DataSource = dsProdutos; dgvProdutos.DataMember = tabela; btnIncluir.Enabled = true; btnExcluir.Enabled = true; btnAlterar.Enabled = true; } No evento Click do botão Incluir temos o código que inclui um novo registro na tabela Products. Estamos usando o método NewRow() e incluindo uma nova linha na tabela; Estou incluindo um produto com o nome Macoratti_ Estamos usando o procedimento básico para incluir dados em um dataset : criando uma nova linha e em seguida adicionando a coleção DataRow do DataTable no DataSet No nosso caso estamos fazendo isso em um DataSet não tipado chamando o método NewRow para criar uma nova linha vazia; esta linha herda a estrutura da coluna da coleção DataColumnCollection. Em seguida incluímos(add) a linha na coleção de linhas e atualizamos(update) o dataset. private void btnIncluir_Click(object sender, EventArgs e) { daProdutos = new SqlDataAdapter("SELECT ProductID, ProductName FROM Products", conn); SqlCommandBuilder cmdbldr = new SqlCommandBuilder(daProdutos); dsProdutos = new DataSet(); daProdutos.Fill(dsProdutos); DataRow registro = dsProdutos.Tables[0].NewRow(); registro["ProductName"] = "Macoratti_"; dsProdutos.Tables[0].Rows.Add(registro); //atualiza o dataset daProdutos.Update(dsProdutos); MessageBox.Show("Registro incluido."); } O código do evento Click do botão Alterar é visto a seguir. - No código obtemos o valor do código do produto a partir da linha selecionada no DataGridView e armazenamos na variável codigo; - Em seguida verificamos se o codigo possui um valor válido; - Usamos o método Find do DataTable para localizar o registro com o código obtido e atualizamos o nome do produto com um sinal de #; private void btnAlterar_Click(object sender, EventArgs e) { daProdutos = new SqlDataAdapter("SELECT ProductID, ProductName FROM Products order by ProductID", conn); SqlCommandBuilder cmdbldr = new SqlCommandBuilder(daProdutos); dsProdutos = new DataSet(); daProdutos.Fill(dsProdutos); DataColumn[] chave = new DataColumn[1]; chave[0] = dsProdutos.Tables[0].Columns[0]; dsProdutos.Tables[0].PrimaryKey = chave; codigo = dgvProdutos.CurrentRow.Cells["ProductID"].Valu e.ToString(); if (codigo != null || !codigo.Equals("")) { DataRow registro = dsProdutos.Tables[0].Rows.Find(codigo); registro["ProductName"] = registro["ProductName"] + " # "; daProdutos.Update(dsProdutos); MessageBox.Show("Registro alterado."); } else { MessageBox.Show("Registro não localizado."); } } O código do evento Click do botão Excluir é visto a seguir. - No código obtemos o valor do código do produto a partir da linha selecionada no DataGridView e armazenamos na variável codigo; - Em seguida verificamos se o codigo possui um valor válido; - Usamos o método Find do DataTable para localizar o registro com o código obtido; - Para excluir usamos o método Delete; private void btnExcluir_Click(object sender, EventArgs e) { daProdutos = new SqlDataAdapter("SELECT ProductID, ProductName FROM Products order by ProductID", conn); SqlCommandBuilder cmdbldr = new SqlCommandBuilder(daProdutos); dsProdutos = new DataSet(); daProdutos.Fill(dsProdutos); DataColumn[] chave = new DataColumn[1]; chave[0] = dsProdutos.Tables[0].Columns[0]; dsProdutos.Tables[0].PrimaryKey = chave; codigo = dgvProdutos.CurrentRow.Cells["ProductID"].Valu e.ToString(); if (codigo != null || !codigo.Equals("")) { DataRow registro = dsProdutos.Tables[0].Rows.Find(codigo); registro.Delete(); daProdutos.Update(dsProdutos); MessageBox.Show("Registro excluido."); } else { MessageBox.Show("Registro não localizado."); } } O resultado obtido pode ser visto na figura abaixo: Com isso mostrei os procedimentos básicos de como atualizar um dataset não tipado usando ADO .NET;