C# - Usando DataTableReader com Windows Forms


O DataSet pode ser considerado o principal objeto das aplicações centrada 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 esta manipulando.

Um DataReader (SqlDataReader/OledbDataReader) é muito mais rápido que um DataSet e consome menos memória mas 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, dai 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. Para saber mais acessa o meu artigo :  Usando o SQL Server Management Studio

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 :

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 valres 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 o qual 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á alterado. 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á ser Alterado.

O método Load consome o primeiro conjunto de registro a partir da IDataReader carregada, e 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 esta carregando dados a partir de uma instância IDataReader:

Quando estiver trabalhando como esquema o método Load pode encontrar 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 e o valor original para cada coluna.

Se a linha existente e a linha que esta 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 evento 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 ai. Muitas vezes temos um recurso importante a 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)

Aguarde mais artigos sobre ADO .NET com C#.

Eu sei é apenas C#, mas eu gosto...

Referências:


José Carlos Macoratti