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
###
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