.NET

1 out, 2009

C# – Usando DataTableReader com Windows Forms

Publicidade

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…