DevMedia
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Este é um post disponível para assinantes MVP
Este post também está disponível para assinantes da Easy .net magazine
ou para quem possui Créditos DevMedia.

Clique aqui para saber como acessar este post

1) Torne-se um assinante MVP e por apenas R$ 59,90 por mês você terá acesso completo a todos os posts. Assinar MVP

2) Adquira Créditos: comprando R$ 180,00 em créditos esse post custará R$ 1,20. Comprar Créditos

post favorito     comentários
easy .net Magazine 11 - Índice

ADO.NET- Artigo easy .net Magazine 11

O artigo descreve o conjunto formado pelo ADO.NET do Framework .NET. Este é composto de namespaces, classes e formas de trabalho que possibilitam um acesso mais simplificado a dados armazenados em diversos tipos de gerenciadores de banco de dados. Além de uma descrição dos principais recursos, são consideradas também as melhores práticas a serem adotadas ao usar estas tecnologias, pensando principalmente em desempenho e em diminuição dos problemas que poderão ocorrer.

[fechar]

Você não gostou da qualidade deste conteúdo?

(opcional) Você poderia comentar o que não lhe agradou?

Confirmo meu voto negativo
ADO.NET
Como obter melhores resultados no acesso a banco de dados

 


Boas Práticas com ADO.NET
As tecnologias devem facilitar o trabalho em qualquer área. Ao desenvolver aplicações voltadas para o trabalho com bancos de dados, muitos problemas precisam ser resolvidos com ADO.NET. Entretanto, como qualquer ferramenta, se não houver um conhecimento maior do seu funcionamento, alguns enganos podem comprometer o resultado final. Ao demonstrar a infraestrutura básica desta tecnologia, qual componente usar em cada caso e algumas boas práticas a serem adotadas, será possível fortalecer alguns conceitos que ajudarão ao desenvolver projetos para o mundo real. Um projeto de exemplo foi criado com o propósito de usar algumas das ideias expostas. Este projeto está colocado mais à frente no artigo.

ADO.NET e a camada de acesso aos dados
O ADO.NET é um conjunto de namespaces, classes e interfaces, usado para providenciar um acesso consistente aos diversos tipos de fonte de dados. Outro objetivo de ADO.NET é diminuir significativamente a quantidade de código necessário para interagir com as fontes de dados. Com seus componentes, muitas tarefas podem ser configuradas visualmente, principalmente se o desenvolvedor estiver usando as versões mais recentes do Visual Studio. Uma das principais tarefas do ADO.NET é separar as tarefas de acesso aos dados das de manipulação em partes que podem trabalhar independentes ou em conjunto
Modelos de acesso conectado e desconectado
Existem várias questões a serem consideradas quando se trabalha com ADO.NET. A primeira sem dúvida é o modelo de acesso aos dados que pode ser feito de duas formas: conectado e desconectado. Ao trabalhar conectado o desenvolvedor precisa estabelecer um canal com a fonte de dados por onde será feita a leitura ou escrita com os dados. Isto só pode ser feito enquanto o canal estiver aberto.
Operações tipicamente conectadas são:
1.    Execução de inserção, alteração e exclusão dos dados no banco;
2.    Leitura unidirecional dos dados. Este tipo de leitura não permite uma navegação bidirecional pelos registros. Um uso típico é a leitura dos dados para geração de relatórios ou exibição em páginas estáticas.
As classes que são indicadas para este trabalho são implementações das Interfaces IDbCommand, IDbDataReader e IDbConnection. Mais à frente será considerada a questão dos DataProviders, que fazem implementações customizadas destas classes.
O modelo de acesso permite que se carreguem os dados para serem usados pela aplicação sem ser necessário manter uma conexão permanente com a fonte de dados. Assim, podem-se editar os dados, navegar pelos registros sendo que só quando for necessário, seja estabelecida uma conexão com o banco de dados para o eventual envio das alterações feitas localmente. O trabalho é feito basicamente com as classes DataTable e DataSet e com as implementações das interfaces de IDataAdapter e IDataParameter.

Nota: Estas interfaces definem o modelo de acesso que o Framework .NET provê. Cada banco de dados deve implementar as classes mais apropriadas para o acesso sendo que os padrões do ADO.NET são: System.Data.OleDb, Sytem.Data.Odbc, System.Data.SqlClient e System.Data.OracleClient (que deve ser baixado).

Data Providers
Os Data Providers proporcionam uma camada mínima entre as fontes de dados e o código por serem leves e causarem pouco impacto. Estes componentes servem de pontes entre a fonte de dados e a aplicação. Uma preocupação inicial é usar o data provider correto para o tipo de banco de dados que se está usando. Observe na Figura 1 onde é feito um comparativo do acesso ao SQL Server usando o data provider nativo e outros. Note que usando o SqlClient, o número de camadas até o banco é mínimo. Os principais data providers do framework são os da Tabela 1.


 

DataSet e TableAdapter
Os DataSets são os componentes usados para armazenar os dados. Representam os dados do banco de dados armazenados na memória e estruturados em tabelas. Podem ser definidos como um conjunto de objetos DataTable, também usados em conjunto com TableAdapters – estes últimos, derivados dos DataAdapters. Com estes componentes no projeto o desenvolvedor define as consultas ao banco de dados para recuperar os dados em DataTables, definindo as consultas com TableAdapters vinculados com estas. É indicado para o trabalho desconectado. Ao definir os TableAdapters vinculados com o DataTable, cria-se uma classe fortemente tipada com as colunas do banco de dados mapeadas para o projeto e com a possibilidade de definir várias consultas, sendo que cada uma gera um método Fill para preenchimento dos dados.
A classe DataSet é definida no namespace System.Data. Pode ser definida via código ou visualmente quando se usa o Visual Studio. Um dos pontos principais a se observar é que ao usar o designer, muito código é gerado para implementar as funcionalidades básicas, como a geração automática das instruções SQL para inserção, atualização e exclusão dos dados. Se muitas tabelas forem definidas sem critério e o DataSet ficar muito extenso, a sua manipulação no projeto do Visual Studio se torna muito lenta. Já citei exemplos em artigos anteriores onde a geração de uma tabela num DataSet gerou um código de mais de três mil linhas. Por isto, é importante tomar cuidado. Se for usar o DataSet, procure separar por partes do sistema. Você pode criar um DataSet para cada módulo como, por exemplo: Estoque, Finanças etc.
Usando DataAdapter
Um DataAdapter implementa a interface IDbDataAdapter e consiste entre outros componentes de um objeto para conexão com o banco e pelo menos uma instância de uma classe que implementa IDbCommand para a configuração das instruções SQL.

Nota: Como foi explicado anteriormente, as classes para o acesso aos diversos tipos de banco de dados dependem muito do data provider utilizado. Por este motivo, estou citando as interfaces para poder deixar entendido que a funcionalidade discutida está presente em todos os data providers.

Quando usar DataAdapter não é necessário configurar um objeto conection. Ao usar a string de conexão diretamente na instância do objeto, ao executar o método Fill a conexão é fechada automaticamente. Assim uma maneira típica de criar uma instância deste objeto, considerando, por exemplo, a classe SqlDataAdapter, seria desta forma:

      using(SqlDataAdapter dataAdapter = new SqlDataAdapter("select * from customers",
        @"Data Source=.\sqlexpress;initial catalog=Northwind;integrated security=True;")) {
        using(DataTable tabela = new DataTable()) {
            dataAdapter.Fill(tabela);

Neste código foi passada primeiramente a instrução SQL e em seguida a string de conexão. Note que nenhum objeto SqlConnection foi criado. Após executar o método Fill, a conexão está fechada.
Valores nulos
No Framework .NET existe o valor nulo que é a mesma coisa que um objeto não ter um valor definido. Entretanto, existem casos em que os tipos, principalmente numéricos, não aceitam este valor que não é igual a zero e nem a nenhum número, mas uma ausência de valores. Ao se tentar atribuir um valor nulo para um tipo que não o aceita, o compilador acusa o erro e não prossegue. Mas existem alguns casos em que isto não pode ser detectado durante a compilação, como por exemplo:
•    Quando os dados estão sendo lidos em um DataReader: se estiver usando GetInt32 ou GetDecimal, ou Get<tipo>, se o valor no banco estiver nulo, isso irá causar um NullReferenceException;
•    Ao tentar converter valores nulos vindos do banco com os métodos Parse existentes nos tipos ou com a classe Convert;
•    Enviando valores como parâmetros para instruções SQL.
Para evitar estes problemas algumas medidas podem ser tomadas:
•    Usar as funções ISNULL ou COALESCE na instrução SQL (usando o SQL Server 2008) ou sua equivalente em outros bancos de dados para tratamento dos valores nulos;
•    Usar o método TryParse para converter os dados;
•    Se for necessário enviar valores nulos para uma instrução SQL como parâmetro usar System.DbNull.Value ou então, se estiver usando SQL Server, verificar o namespace System.Data.SqlTypes para enviar valores nulos para cada tipo de dado específico.
Cuidados com o DataReader
DataReaders são usados para obter os dados em modo conectado, em um único sentido, sem possibilidade de navegação bidirecional pelos resultados. Pode-se obter os valores de cada coluna acessando pelo nome da coluna, como por exemplo:

string companyName = reader[“CompanyName”].ToString();

Assim, os valores são retornados do tipo object e devem ser convertidos para o tipo de destino desejado. Outra forma é usando os métodos que obtêm o valor já no tipo padrão: GetInt32, GetInt16, GetDecimal, GetString e assim por diante. Neste caso é preciso passar o índice correspondente ao campo retornado dentro da instrução SQL (o que não é recomendável se você definir uma consulta com “SELECT * FROM...”).
Considerando a seguinte consulta à tabela Orders do banco de dados Northwind:

SELECT OrderID, CustomerID, OrderDate, Freight
FROM Orders

Para ler os dados com o DataReader o código seria o seguinte:

int orderID = reader.GetInt32(0);
string customerID = reader.GetString(1);
DateTime orderDate = reader.GetDateTime(2);
decimal Freight = reader.GetDecimal(3);

Outro ponto a considerar é que diferentemente da classe TableAdapter/DataAdapter, ao usar DataReader a conexão deve ser explicitamente fechada pelo método Close(), pois não é automaticamente fechada ao término do resultado da consulta. Fazendo isto, garante-se a liberação da conexão ao banco de dados que controla o número de conexões abertas, o que é limitado pelo pool de conexões.
"

A exibição deste artigo foi interrompida

Este post está disponível para assinantes MVP.



A DevMedia é um portal para analistas, desenvolvedores de sistemas, gerentes e DBAs com milhares de artigos, dicas, cursos e videoaulas gratuitos e exclusivos para assinantes.

O que você achou deste post?
Publicidade
Serviços

Mais posts