Você está na página 1de 69

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 multi-
plataforma 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.mono-
project.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 define uma variável string nomeusario;
nomesuario;
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
{
/// <summary>
/// A documentation sample -
the short description goes here
/// </summary>
/// <remarks>Where a longer description would go<
/remarks>
class ClassExample
{
/// <summary>
/// A member variable
/// </summary>
private string m_str;

/// <summary>
/// A method example
/// </summary>
/// <param name="val">a new value to be saved<
/param>
/// <returns>the length of the string</returns>
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
<summary> … Breve descrição de uma classe,
</summary> método ou propriedade.
<remarks> … Descrição mais detalhada.
</remarks>
<para> ... Permite delinear parágrafos dentro
</para> da tag <remarks>
<list type="…"> Permite usar marcadores para
… </list> formatar uma descrição. Os tipos de
marcadores podem ser “bullet”,
“number” e “table”.
<example> … Para disponibilizar um exemplo de
</example> como usar um método, propriedade
ou outro membro da biblioteca.
<code> … Para indicar que o texto incluído é
</code> código da aplicação.
<c> … </c> 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.
<see Indica uma referencia a outro
cref="member"/> membro ou campo. O compilador
verifica se o membro realmente
existe.
<exception> … Para fazer a descrição de uma
</exception> exceção.
<permission> … Para documentar a acessibilidade.
</permission>
<param Para documentar um parâmetro de
name="name"> … um método.
</param>
<returns> … Para documentar um valor e seu
</returns> tipo retornado de um método.
<value> … Para descrever uma propriedade
</value>
A linguagem C# possui uma coleção de palavras chaves
ou reservadas que são usadas pela linguagem conforme
abaixo:
Abstract as base bool break
Byte case catch char checked
Class const continue decimal default
Delegate do double else enum
Event explicit extern false finally
Fixed float for foreach goto
If implicit in int interface
Internal is lock long namespace
New null object operator out
Override params private protected public
Readonly ref return sbyte sealed
Short sizeof stackalloc static string
Struct switch this throw true
Try typeof uint ulong unchecked
Unsafe ushort using virtual volatile
Void while . . .
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 System.Boolean Representa valores true e
false
byte System.Byte inteiro de 8-bit sem sinal
sbyte System.SByte
char System.Char Um caractere
decimal System.Decimal Tipo numérico para cálculos
financeiros
double System.Double Ponto flutuante de precisão
dupla
float System.Single Ponto Flutuante de precisão
simples
int System.Int32 Inteiro
uint System.UInt32 inteiro sem sinal
long System.Int64 Inteiro Longo
ulong System.UInt64 inteiro longo sem sinal
object System.Object objeto
short System.Int16 Inteiro Short
ushort System.UInt16 Um inteiro short sem sinal
string System.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.

Tipo C# Valores possíveis de se armazenar


bool Verdadeiro ou Falso
byte 0 a 255 (8 bits)
sbyte -128 a 127 (8 bits)
char 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 ±1.5 × 10-45 a ±3.4 × 1038 (32 bits)
int -2,147,483,648 a 2,147,483,647 (32 bits)
uint 0 a 4,294,967,295 (32 bits)
long –9,223,372,036,854,775,808 a
9,223,372,036,854,775,807 (64 bits)
ulong 0 a 18,446,744,073,709,551,615 (64 bits)
object Qualquer tipo.
short -32,768 a 32,767 (16 bits)
ushort 0 a 65,535 (16 bits)
string Seqüência de caracteres (16 bits por
caractere)

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 Resultado do laço


int i = 0; while:
while ( i < 5 ) 0
{ 1
Console.WriteLine ( 2
i ); 3
++i; 4
}
repete 5 vezes e imprime o
valor de i.
for Resultado do laço For:
int i = 0; 0
for ( int i = 0; i < 5; i++ 1
) 2
{ 3
Console.WriteLine ( 4
i );
}

do ... while O laço Do/While é


int i = 0; quase igual ao laço
do While.
{
Console.WriteLine ( i ); A única diferença é que
o código dentro do laço
i++;
será executado pelo
} menos uma vez pois a
while ( i < 5 ); seguir é feita a
verificação da condição.

foreach O laço - foreach - pode


string [] nomes = new ser usado para iterar
string[] { "Macoratti", através de
"Miriam"}; uma coleção como um
foreach ( string nome in array , ArrayList ,etc.
nomes ) A saida para o laço é :
{ Macoratti
Console.WriteLine ( Miriam
nome );
}
Operadores Condicionais

if ... else Operador usado


para testar
string nome = "Macoratti"; condições lógicas
if ( nome == "Pedro" ) e executar a
{ porção de código
Console.WriteLine( "Você baseado na
esta no bloco 'if'" ); condição.
} No exemplo se o
else nome definido for
{ igual a 'Pedro'
Console.WriteLine( "Você teremos: Você
esta no bloco 'else'" ); 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 O comando break
string [] nomes = new string[] { é usado para a
"Macoratti", "Miriam", "Pedro"}; saída de laços (
foreach ( string nome in while, for , switch,
nomes ) etc..)
{ No exemplo ao lado
Console.WriteLine ( quando o nome for
nome ); igual a 'Miriam'
if ( nome == "Miriam" ) haverá a saída do
break; laço devido ao
} comando break;
A saida será:
Macoratti
Miriam
continue O comando
continue também é
string [] nomes = new string[] { usado em
"Macoratti", "Miriam", "Pedro"}; laços(while, for,
foreach ( string nome in etc.) quando em
nomes ) execução o
{ comando continue
if ( nome == "Miriam" ) irá mover a
continue; execução para o
Console.WriteLine ( próxima iteração no
nome ); laço sem executar
} as linhas de código
depois de continue.
No exemplo a saída
será:
Macoratti
Pedro
switch O comando Switch
int i = 6; é uma boa opção se
switch ( i ) você tiver que
{ escrever muitas
case 5: condições if..else.
Console.WriteLine( No exemplo ,
"Valor de i é : " + 5 ); dependendo do
break; valor do item
case 6: condicional o código
Console.WriteLine( do case apropriado
"Valor de i é : " + 6 ); será executado.
break; A saída para o
case 4: exemplo será:
Console.WriteLine( Valor de i é : 6
"Valor de i é : " + 4 ); Note que usamos
break; instruções break
default: para sair do bloco.
Console.WriteLine( Sem isto o próximo
"Valor de i é : " + i ); bloco Case seria
break; executado.
}
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 do API Descrição
Provedor prefixo
ODBC Data Odbc Fonte de dados com uma
Provider interface ODBC interface.
Geralmente usada para banco
de dados antigos;
OleDb Data OleDb Fonte de dados que expõe
Provider uma interface OleDb
interface, ou seja: Access ou
Excel;
Oracle Data Oracle Para banco de dados Oracle;
Provider
SQL Data Sql Para interação com o
Provider Microsoft SQL Server;

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 Descrição
Coleções

Relations Uma coleção de relações hospedadas em um


objeto DataRelationCollection que liga
tabelas através de chaves estrangeira
Tables Uma coleção de tabelas que armazena os
dados atuais
Métodos

AcceptChanges Grava todas as alterações para o DataSet


Clear Remove todas as linhas de todas as tabelas
Clone Faz uma cópia da estrutura mas não os
dados de um DataSet
Copy 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
GetXml Retorna uma representação exm XML dos
dados
GetXmlSchema Retorna uma representação XML da
estrutura de um DataSet
HasChanges Retorna um valor indicando que existe
mudanças pendentes
InferXmlSchema Infere a estrutura de um DataSet baseada
em um arquivo ou fluxo
Merge Mescla o DataSet com o provedor
ReadXml Carrega um esquema XML e dados para um
DataSet
ReadXmlSchema Carrega um esquem XML para um DataSet
Reset Reverte o DataSet ao seu estado original
WriteXML 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.
System.Data.Odbc Define classes que trabalham com
fonte de dados ODBC usando o
provedor .NET 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;
DataSource Retorna o nome da instância do
banco de dados usado pelo
objeto Connection;
State Retorna o estado atual da
conexão: Valores possíveis :
• Broken
• Closed
• Connecting
• Executing
• Fetching
• Open

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 Defina para SSPI para fazer a
Security 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 Nome do usuário definido no SQL
Server.
Password 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;

/// <summary>
/// Demonstra como trabalhar abrir uma conexão
com SqlConnection
/// </summary>
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 sobre o
objeto SqlCommand
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 Descrição
ExecuteReader 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 SqlConnection cn = null;
= new SqlCommand cm = null;
SqlConnection(connection try
String)) {
{ cn = new
using (SqlCommand SqlConnection(connection
cm = new String);
SqlCommand(commandS cm = new
tring, cn)) SqlCommand(commandS
{ tring, cn);
cn.Open(); cn.Open();

cm.ExecuteNonQuery(); 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-para-
frente
• 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 SqlCommand(sql,
adoConn);

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/en-
us/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 prático usando
DataReader
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 a qual se
aplica
// Preenche o valor do parâmetro
com o texto informado
// na caixa de texto : 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 ProductName,UnitPrice FROM
Products 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 uma página ASP .NET Em um arquivo
C#:
<%@ Import using
Namespace="System.Data" %> System.Data;
Para criar um objeto DataSet você usa a seguinte
sintaxe: DataSet <nomedoDataSet> = 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
Excluir-
btnExcluir

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;

Você também pode gostar