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'AnnaA 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”:
Figura 1: Criando novo projeto
Adicione um Button e um DataGrid:, ambos a partir da página “Win Forms” do ToolBox:
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:
Figura 3: Resultado do código
Observe que é possível editar, acrescentar e eliminar dados à tabela editando o “grid” diretamente com o teclado:
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); } }