O DataSet pode ser considerado o
principal objeto das aplicações centradas em dados da tecnologia
ADO .NET e contém uma representação do banco de dados em
memória, representado por uma coleção de tabelas com seus
relacionamentos e restrições.
Veja abaixo uma figura representando
o DataSet no namespace System.Data da arquitetura ADO .NET :

O problema do dataset é que ele
pode ser lento, dependendo da situação e a maneira como você o
manipula.
Um DataReader (SqlDataReader/OledbDataReader)
é muito mais rápido que um DataSet e consome menos memória. O grande problema do DataReader é que ele
sempre requer uma conexão ativa, e, para usá-lo temos que
fechar a conexão.
Não haveria uma forma mais rápida
de tratar dados? Sim, seus problemas acabaram: use o DataTableReader…
Um DataTableReader
obtém o conteúdo de um ou mais de um objeto DataTable
na forma de um conjunto de dados somente leitura de acesso
sequencial.
Ele é uma combinação de um DataTable
e um DataReader:
- Em um DataTable, podemos armazenar
uma única tabela de um banco de dados com todas as constraints
no modo desconectado e podemos efetuar toda a manipulação de
dados com ele; - Um DataReader pode conter uma
única tabela de registros, com dados somente leitura de acesso
sequencial, e para isso precisamos ter um conexão aberta com o
banco de dados; daí não podemos efetuar a manipulação dos
dados.
Pois o DataTableReader juntou o
melhor dos dois mundos: ele pode conter mais do que um
DataTable em um modo desconectado como um conjunto de dados
somente leitura de acesso sequencial.
A classe DataTableReader
foi desenvolvida de forma a trabalhar no modo desconectado. A
iteração nas linhas é feita a partir do cache. Os dados no
cache podem ser modificados enquanto o DataTableReader
esta ativo.
Criando
um DataTableReader
Obs: No exemplo deste
artigo eu estou acessando o banco de dados Agenda.mdf criado no Management
Studio e a tabela Clientes que possui os campos : id, nome e email.
Abra o Visual C# 2008 Express
Edition (podemos usar também o SharpDevelop 3.0) e crie um novo projeto com o nome
U_DataTableReader;
A seguir, inclua no formulário
padrão form1.cs , a partir da ToolBox, os controles:
- MenuStrip – Defina a opção
Carregar no menu com dois itens: ListBox e DataGridView;

- TabControl –
Altere a propriedade Text de cada um dos TabPages do
controle, conforme a figura abaixo:

A seguir, inclua na primeira TabPage
o controle ListBox, e na segunda TabPage o controle DataGridView
conforme abaixo:


Um DataTableReader
pode ser criado a partir de qualquer DataTable através do
método CreateDataReader. Vejamos um exemplo:
Coloque o código abaixo no evento
Click do item ListBox do Menu Carregar:
void ListBoxToolStripMenuItemClick(object sender, EventArgs e)
{
string sql = "Select * from Clientes";
string strconn = @"Data Source=.\SQLEXPRESS;Initial Catalog=Agenda;Integrated Security=True";
SqlDataAdapter da = new SqlDataAdapter(sql, strconn);
DataTable dt = new DataTable();
da.Fill(dt);
DataTableReader dtr = dt.CreateDataReader();
if (dtr.HasRows)
{
while (dtr.Read())
{
lstb_Resultado.Items.Add(dtr["nome"].ToString());
}
}
else
{
MessageBox.Show("Não há dados");
}
}
Execute o projeto e clique no item
ListBox do menu Carregar:

Exibindo
um DataTableReader em controles de grid
Uma outra característica da classe
DataTableReader é que podemos usá-la como uma fonte de dados
para popular um DataSet ou DataTable e, em seguida, exibir o
resultado em um controle de Grid como DataGridView ou GridView.
Fazemos isso usando o método Load
do DataTableReader.
O método Load preenche um DataTable
com os valores a partir de uma fonte de dados usando a interface
IDataReader. Se o DataTable já contiver linhas, os dados oriundos
da fonte de dados serão mesclados com as linhas existentes, de
acordo com o valor do parâmetro LoadOption, que pode ser:
| Load option | comportamento |
|---|---|
| OverwriteChanges | Os valores de entrada para essa linha serão gravados tanto no valor atual e nas versões de valor original dos dados para cada coluna. |
| PreserveChanges | Os valores de entrada para essa linha serão gravados à versão original do valor de cada coluna. A versão atual dos dados em cada coluna não será alterada. Este é padrão. |
| Upsert | Os valores de entrada para essa linha serão gravados para a versão atual de cada coluna. A versão original de dados de cada coluna não será alterada. |
O método Load consome o primeiro
conjunto de registro a partir da IDataReader carregada. Após
isso, defina posição do leitor para o próximo conjunto de
registros se houver. Este método leva em consideração 3
aspectos específicos quando está carregando dados a partir de
uma instância IDataReader:
- O esquema;
- Os dados;
- Eventos de operações;
Quando estiver trabalhando como
esquema o método Load, pode ser que encontre as seguintes condições:
| Condição | Comportamento |
|---|---|
| O DataTable não possui um esquema. |
O método Load infere o esquema baseado no conjunto de registros a partir da IDataReader importada. |
| O DataTable possui um esquema incompatível com o esquema carregado. |
O método Load lança um exceção correspondente a um erro particular que ocorre quando vai tentar carregar os dados no esquema incompatível. |
| Os esquemas são compatíveis mas o conjunto de registros carregado contém colunas que não existem no DataTable. |
O método Load inclui uma coluna extra ao esquema do DataTable. O método lança uma exceção se as colunas contiverem valores compatíveis. O método também retorna a informação da constraint a partir do conjunto de registros para todas as colunas incluídas. |
| O esquemas são compatíveis mas o conjunto de registros carregado contém menos colunas que o DataTable. |
Se a coluna que faltar possuir um valor padrão ou o tipo da coluna de dados for nullable, o método permite que linhas sejam incluídas substituindo as linhas padrão ou os valores nulos para a coluna em falta. |
Você deve considerar também que
cada linha no DataTable mantém tanto o valor atual como o original para cada coluna.
Se a linha existente é a linha que
está sendo carregada contiverem valores de chave primária, a
linha é processada usando o seu valor atual, de outra forma ela
é tratada como uma nova linha.
Em termos de eventos, o RowChanging
ocorre antes de cada linha ser alterada, e o evento RowChanged
ocorre depois que cada linha foi alterada. Em cada caso, a
propriedade Action da instância DataRowChangedEventArgs
passada para o manipulador de eventos contém a informação
sobre a ação particular associada com o evento.
Vejamos um exemplo:
Coloque o código a seguir no evento
Click do item DataGridView do menu Carregar:
void DataGridViewToolStripMenuItemClick(object sender, EventArgs e)
{
DataSet ds = new DataSet();
string sql = "Select * from Clientes";
string strconn = @"Data Source=.\SQLEXPRESS;Initial Catalog=Agenda;Integrated Security=True";
SqlDataAdapter da = new SqlDataAdapter(sql, strconn);
DataTable dtClientes = new DataTable();
da.Fill(dtClientes);
ds.Tables.Add(dtClientes);
DataTableReader dtr = new DataTableReader(ds.Tables[0]);
dtClientes.Load(dtr, LoadOption.OverwriteChanges);
gdv_Resultado.DataSource = dtClientes;
}
Executando o projeto e clicando na
opção do menu iremos obter:

E é isso aí. Muitas vezes temos um
recurso importante à nossa disposição e não o usamos por falta
de informação. Fica aqui o registro.
Pegue o projeto completo aqui: U_DataTableReader.zip (sem a base de
dados).
Eu sei, é apenas C#, mas eu gosto…




