Desenvolvimento - C#

Tabelas no .NET

A arquitetura .NET da Microsoft traz uma nova biblioteca para acesso a bancos de dados chamada ADO.NET. Uma das principais características do ADO.NET é a de permitir o acesso a bancos de dados desconectado, de forma semelhante do Delphi usando “CachedUpdates := true” e o componente “TUpdateSQL”. A principal diferença em relação ao Delphi é que o esquema todo é mais sofisticado e mais flexível.

por Mauro Sant'Anna



A arquitetura .NET da Microsoft traz uma nova biblioteca para acesso a bancos de dados chamada ADO.NET. Uma das principais características do ADO.NET é a de permitir o acesso a bancos de dados desconectado, de forma semelhante do Delphi usando “CachedUpdates := true” e o componente “TUpdateSQL”. A principal diferença em relação ao Delphi é que o esquema todo é mais sofisticado e mais flexível. No modo desconectado, você trabalha com uma cópia em memória de parte do banco de dados. Por esta razão é bastante importante a capacidade de representar tabelas em memória. Neste artigo iremos ver as principais características das tabelas em memória em programas .NET com janelas.

Abstraindo uma tabela

Normalmente pensamos em uma “tabela” como algo exclusivamente amarrado a um banco de dados físico ou, pelo menos, como resultado de uma consulta em SQL. O ADO.NET define uma tabela no componente DataTable que não está necessariamente ligada a tabelas físicas de bancos de dados.

Um DataTable contém basicamente as seguintes informações:

  • “Estrutura” da tabela, essencialmente a quantidade, nomes e tipos das “colunas” (ou “campos”);
  • Uma coleção de “linhas” (ou “registros”) contendo os dados e seguindo a mesma estrutura da tabela.

A coleção de linhas é na verdade uma coleção de componentes DataRow. O Componente DataRow contém informações sobre todas as colunas (“campos”) da tabela.

Observe que um componente DataTable é perfeitamente definido sem que tenhamos que fazer acesso a bancos de dados. Podemos muito bem criar uma “tabela em memória” que atende a estas características. É exatamente isso que vamos fazer no exemplo seguinte.

Tabela em Memória

Crie um novo aplicativo “WinForms” na linguagem C# pedindo “File | New Project”:

Criando novo projeto

Figura 1: Criando novo projeto

Adicione um Button e um DataGrid:, ambos a partir da página “Win Forms” do ToolBox:

Layout do form

Figura 2: Layout do form

Dê um clique duplo no botão e acrescente o seguinte código:

Listagem 1: Listando dados

DataTable Tbl;
protected void button1_Click (object sender, System.EventArgs e)
{
// Cria uma nova tabela
Tbl = new DataTable();
// Adiciona os nomes e tipos das colunas
Tbl.Columns.Add("Nome", typeof(string));
Tbl.Columns.Add("Nascimento", typeof(DateTime));
Tbl.Columns.Add("Salario", typeof(decimal));
Tbl.Columns.Add("UF", typeof(string));
// Esta coluna é "calculada", ou seja,
// seu valor vem de uma expressão
Tbl.Columns.Add(new DataColumn("Salario (US$)",
typeof(decimal), "Salario / 2.50"));
// Declara classe para gerenciar registros
DataRow Linha;
// ******************** Forma 1 de criar registro
// e acrescentar no DataGrid
// Cria uma nova linha
Linha = Tbl.NewRow();
// Coloca os dados em cada uma das colunas desta linha
Linha[0] = "Maria da Silva";
Linha[1] = new DateTime(1977, 12, 5);
Linha[2] = 3400m;
Linha[3] = "SC";
// Adiciona a linha na tabela
Tbl.Rows.Add(Linha);
// ********* Forma 2 de criar registro e acrescentar no DataGrid
// Note o uso dos nomes dos campos
// Cria uma nova linha
Linha = Tbl.NewRow();
// Coloca os dados em cada uma das colunas desta linha
Linha["Nome"] = "José Souza";
Linha["Nascimento"] = new DateTime(1981, 3, 25);
Linha["Salario"] = 1835.45m;
Linha["UF"] = "RS";
// Adiciona a linha na tabela
Tbl.Rows.Add(Linha);
// ******* Forma 3 de criar registro e acrescentar no DataGrid
// Cria uma nova linha
Linha = Tbl.NewRow();
// Coloca os dados em cada uma das colunas desta linha
Linha.ItemArray = new object[] {"Maricota das Couves",
new DateTime(1966, 5, 15), 6430, "PR"};
// Adiciona a linha na tabela
Tbl.Rows.Add(Linha);
// ****** Forma 4 de criar registro e acrescentar no DataGrid
Tbl.Rows.Add(new object[]{"Josenildo Oliveira",
new DateTime(1955, 1, 12), 1150, "SC"});
// Exibe a tabela no DataGrid
dataGrid1.DataSource = Tbl;
// Muda o alinhamento no grid
dataGrid1.GridColumns[2].Alignment = HorizontalAlignment.Right;
}

Observe alguns pontos importantes no código acima:

  • Estamos criando uma tabela em memória com o comando Tbl = new DataTable();
  • Depois de criar a tabela estamos criando cinco colunas. As quatro primeiras, Nome, Nascimento, Salário e UF contém dados, cada qual de um tipo. A quinta SalarioUS, é calculada a partir da coluna salário através de uma expressão.
  • Existem várias maneiras de acrescentar dados à tabela. A mais simples é a última mostrada, Tbl.Rows.Add(new object[]{"Josenildo Oliveira", new DateTime(1955, 1, 12), 1150, "SC"});
  • Depois de criar a tabela, estamos a exibindo no DataGrid com o comando dataGrid1.DataSource = Tbl;
  • Podemos mudar a forma como cada campo é apresentado no grid modificando propriedades como em dataGrid1.GridColumns[2].Alignment = HorizontalAlignment.Right;

Veja o programa rodando:

Resultado do código

Figura 3: Resultado do código

Observe que é possível editar, acrescentar e eliminar dados à tabela editando o “grid” diretamente com o teclado:

Inserindo novo registro

Figura 4: Inserindo novo registro

Código para acesso aos dados

Uma vez tendo criado a tabela, podemos ler e alterar os dados em memória. O código abaixo calcula a média da coluna “Salario”:

Listagem 2: Calculando a média dos valores listados

// Só continua se a tabela foi realmente criada
if (Tbl != null) {
// Começa total com zero
decimal Total = 0;
// Varre todas as linhas
foreach(DataRow Linha in Tbl.Rows) {
// Verifica se o campo não está nulo
if (!Linha.IsNull("Salario")) {
// Pega o valor corrente
decimal Salario = (decimal) Linha["Salario"];
// Totaliza
Total += Salario;
}
}
// Calcula média
decimal Media = Total / Tbl.Rows.Count;
// Exibe média no formulário
textBox1.Text = Media.Format("n2", null);
}

Note o seguinte:

  • Uso do comando foreach para varrer todos os elementos da tabela;
  • Uso do comando Linha[“Salário”] para ler o valor da coluna. Como o tipo desta propriedade é object, precisamos fazer um “cast” para o tipo adequado.

O exemplo abaixo altera valores na tabela:

Listagem 3: Alterando valores da tabela

// Só continua se a tabela foi realmente criada
if (Tbl != null) {
// Varre todas as linhas
foreach(DataRow Linha in Tbl.Rows) {
// Verifica se o campo não está nulo
if (!Linha.IsNull("Nome")) {
// Pega o valor corrente
string Nome = (string) Linha["Nome"];
// Calcula novo valor
Nome = Nome.ToUpper();
// Altera valor na tabela
Linha["Nome"] = Nome;
}
}
}

Para alterar o valor na tabela usamos o mesmo comando que foi usado para leitura.

Alterando as colunas

Você pode modificar as características das colunas através de suas propriedades. Por exemplo, o exemplo a seguir ajusta alguns valores “default” para as colunas, que serão usados assim que um novo registro for inserido:

Listagem 4: Definindo valores padrão para as colunas

protected void button7_Click (object sender, System.EventArgs e)
{
// Só continua se a tabela foi realmente criada
if (Tbl != null) {
Tbl.Columns["Nome"].DefaultValue = "";
Tbl.Columns["Salario"].DefaultValue = 0;
}
}

Executando Expressões

Podemos executar expressões em uma tabela. Estas expressões incluem operações aritméticas, média, totais, maior/menor etc. Este cálculo pode ser feito com o método Compute do componente DataTable.Veja um exemplo que calcula a média salarial da tabela usada no exemplo:

Listagem 5: Executando expressões matemáticas

protected void button8_Click (object sender, System.EventArgs e)
{
// Só continua se a tabela foi realmente criada
if (Tbl != null) {
// Executa uma expressão na tabela
object Media = Tbl.Compute("Avg(Salario)", "");
if (Media.GetType() != typeof(System.DBNull))
textBox1.Text = ((decimal)Media).Format("n2", null);
}
}

E possível restringir o conjunto de colunas usadas na expressão. O exemplo abaixo pega a unidade da federação e exibe a média apenas para aquele estado:

Listagem 6: Restringindo colunas utilizadas na expresssão

protected void button4_Click (object sender, System.EventArgs e)
{
// Só continua se a tabela foi realmente criada
if (Tbl != null) {
// Executa uma expressão na tabela
object Media = Tbl.Compute("Avg(Salario)",
"UF="" + textBox2.Text + """);
if (Media.GetType() != typeof(System.DBNull))
textBox1.Text = ((decimal)Media).Format("n2", null);
}
}
Mauro Sant'Anna

Mauro Sant'Anna - Mauro tem mais de 20 anos de experiência no desenvolvimento de software, com produtos publicados no Brasil, Portugal e Estados Unidos, além de extensa experiência em treinamento e consultoria no desenvolvimento de software, tanto criando material como ministrando cursos.
Mauro é um "Microsoft Most Valuable Professional" (MVP - www.microsoft.com/mvp), “Microsoft Regional Director” (RD - www.microsoft.com/rd), membro do INETA Speaker’s Bureau (www.ineta.org) e possui as certificações MCP, MCSA (Windows 2000/2003), MCAD (C# e VB), MCDBA, MCSE (Windows 2000/2003).
Sua empresa, a M. A. S Informática (www.mas.com.br), treinou centenas de turmas em desenvolvimento de software nos últimos anos.