Dias atrás estava discutindo sobre algumas classes na possível mudança na arquitetura do projeto no qual eu estou envolvida e, em determinado momento, citaram usar DataSets. Preciso dizer que tive um pequeno espasmo.
Qual era o cenário? Estamos trabalhando em um projeto para um número pequeno de usuários simultâneos (menos de 500), mas com um banco de dados gigante. Há tabelas (sim, SGBD, relacional, tabelas) com mais de 2 bilhões de linhas, e o banco em si tem mais de 80 Gbs. Logo, a camada de acesso aos dados precisa ser cuidada com carinho. Ah! E há muitas, muitas, muitas procedures e um requisito não funcional era que elas não poderiam sair de lá.
No projeto existem classes de modelo (eu não deveria estar chamando elas assim, é só para ilustrar), logo, por que precisamos de DataSets se podemos trabalhar com a classe List? Mas por que não usar a classe DataSet?
A classe DataSet
A classe DataSet fica dentro do namespace System.Data e representa uma estrutura de dados em cache na memória. É como uma cópia do seu banco de dados na memória. Na MSDN é dito que um DataSet é semelhante a uma matriz de objetos Recordset.
Dentro de um DataSet, há uma coleção de DataTable; cada DataTable possui uma coleção de DataRow, DataColumn e Constraint. O DataSet também possui uma coleção de DataRelation. Isso porque eu só citei as mais usadas, já há outras classes dentro dessas. Sim, muita informação do seu banco de dados. E ainda há os meta dados, pois o DataSet é uma pequena cópia de um contexto do banco de dados na sua memória (por favor, não diga que você puxa o seu banco todo para um DataSet) e ele guarda o status de modificação. Por exemplo, se você modifica uma linha, ele guarda qual foi a mudança e se ela já foi “oficializada”. E ainda todos os dados de primaryKeys são guardados.
Outra coisa chata no DataSet é como manipular os dados dentro dele. Por exemplo, para você imprimir na console todo o conteúdo de um DataSet, você precisa percorer tabelas, linhas e colunas e resgatar o valor contido na propriedade atravéz de indexadores, exemplo:
private void PrintRows(DataSet dataSet) { // For each table in the DataSet, print the row values. foreach(DataTable table in dataSet.Tables) { foreach(DataRow row in table.Rows) { foreach (DataColumn column in table.Columns) { Console.WriteLine(row[column]); } } } }
A classe List
A classe List está presente no namespace System.Collections.Generic e é bem mais enxuta do que um DataSet. Ela é dinamica – você pode acrescentar e tirar itens a qualquer momento – e o interessante é que ela tem o conceito de Generics: qualquer coisa pode ficar dentro de uma lista. No DataSet é guardado na memória o tipo de dado de cada campo na tabela, segundo o DbType, mas na lista você pode colocar qualquer tipo primitivo ou objeto. Inclusive uma lista dentro da outra.
Se você quiser manter ainda menos dados na memória, você pode ter um vetor – isso iria consumir bem menos, mas você não teria a flexibilidade da List.
Sem falar que trabalhando com ela, você vai trabalhar diretamente com seus objetos, por exemplo:
private List PopulaMinhaLista(List lista) { MinhaClasse minha = new MinhaClasse(); minha.propriedade = “valor em string aê"; minha.total = 666; lista.Add(minha); return lista; }
Exemplo simples onde eu só coloquei um item lá na lista.
E como eu populo a lista com os dados vindos do banco?
Acredito que eu não precise explicar para todos. Se você já sabe, pule para o próximo tópico com a conclusão. Se não, veja e aprenda:
Imagine que você está usando um DataReader (estamos falando de ado.NET, lembra?), você possui um while que ficará lendo todo o resultado do DataReader, enquanto possuir dados. Dentro desse while você criará um objeto do tipo da sua classe e populará ele e depois acrescentará na sua lista. Simples!
List lista = new List(); SqlDataReader reader = cmd.ExecuteReader(); while (reader.Read()) { MinhaClasse classe = new MinhaClasse(); classe.propriedade = reader["propriedade"].ToString(); classe.total = Convert.Toint32(reader["total"]); lista.Add(classe); }
E qual a vantagem?
Você vai trabalhar com classes e estruturas de dados mais palpáaveis. Vai ser mais fácil aplicar regras de negócio e manipulá-las depois, por exemplo. Validações também são mais fáceis. E tamém, consome-se menos espaço na memória.
Sua equipe vai falar a mesma língua: a da classe. Você se lembra de cor o nome de todas as colunas da sua tabela? Porque ao resgatar um campo de uma DataRow você precisa lembrar!