C# CRUD (Create, Read, Update & Delete)

Introdução

A partir deste artigo o leitor terá a possibilidade de aprender a utilizar as quatro operações mais comuns na interação com a base de dados.

O artigo utiliza o sistema de base de dados MySQL mas poderá ser adaptável, sem grande esforço, a outro SGBD.

Instalação

Para que o leitor consiga estabelecer uma conexão com o MySQL é necessário:

  1. A instalação do MySQL Connector (ver link 1)
  2. Adicionar a referência do MySQL ao projecto (ver link 2)
  3. Criar uma base de dados com duas tabelas jogadores e clubes (ver link 3)

Resultado final

O artigo também exemplifica a utilização do controlo DataGridView em pleno, usufruindo da possibilidade de imagens e listas de itens dentro do mesmo. Todo o código abaixo escrito será utilizado dentro dos eventos deste controlo, pelo que não será necessário a adição de mais nenhum objecto ao formulário.

Resultado final

O leitor poderá fazer download do projecto para fins educacionais (ver link 4).

Estrutura

Uma estrutura de projecto bem delineada poupa-nos imenso tempo. A estrutura deste projecto é muito simples.

Estrutura do projecto

Classes

Neste artigo é necessário a criação de duas classes distintas. A primeira classe (dbconfig) irá tratar da configuração do acesso à base de dados. A segunda classe (dbhandler) irá permitir a realização de queries / operações CRUD.

class dbconfig
  {
    private string server;
    private string user;
    private string password;
    private string database;

    /* Pode-se, desde logo, atribuir valores por defeito */

    public dbconfig(string __server = "localhost", string __user = "root", 
                    string __password = "", string __database = "footballmanager") 
    {
        this.server = __server;
        this.user = __user;
        this.password = __password;
        this.database = __database;
    }

    public string get() { 
        return "Server=" + this.server + ";Database=" + this.database + 
               ";Uid=" + this.user + ";Pwd=" + this.password;
        /* Output: Server=localhost;Database=footballmanager:Uid=root;Pwd= */
    }
}

No construtor da classe desde logo foi assumido quais os valores por defeito de ligação à base de dados. No entanto é dada a possibilidade de, aquando a iniciação da classe, definir a configuração desejada.

dbconfig db = new dbconfig("localhost", "root", "", "outra_base_dados");

Tudo o que é preciso para estabelecer uma ligação com o servidor de MySQL está nesta classe de configuração.

A classe dbhandler é simplista mas totalmente funcional e segura, em termos de realização de queries, pois permite a passagem de parâmetros. Apenas duas funções foram criadas:

  1. Função get() – Realiza a operação Ler (Read), cuja finalidade é devolver informações da base de dados.
  2. Função set() – Realiza as operações de Criar (Create), Actualizar (Update) e Eliminar (Delete).

Para que a utilização desta classe funcione em pleno será necessário adicionar quatro referências.

/* Permite a ligação com a base de dados */
using MySql.Data.MySqlClient; 
/* Permite a utilização da funcionalidade [Optional] <- disponível apenas na 
   framework 4.0 */ 
using System.Runtime.InteropServices; 
/* Permitem a chamada das funções directamente */
using System.Data;
using System.Text.RegularExpressions;

class dbhandler 
  { 
    private dbconfig db;
    private MySqlConnection connection;
    private MySqlCommand command;
    private MySqlDataAdapter dAdapter;
    private DataSet dSet;

    public dbhandler()
    {
        db = new dbconfig();
        connection = new MySqlConnection(db.get());
    }
}

Sempre que a classe dbhandler é iniciada o seu construtor irá chamar o construtor da classe dbconfig e por sua vez estabelecer uma ligação com a base de dados MySQL.

public DataSet get(string __query, [Optional] MySqlParameter[] __param)
  { 
    this.command = new MySqlCommand(__query, this.connection);

    if (__param != null) { this.command.Parameters.AddRange(__param); }

    this.dAdapter = new MySqlDataAdapter(this.command);
    this.dSet = new DataSet();

    /* input exemplo: 'SELECT * FROM tabela WHERE id = @id'
       output: 'FROM tabela' */
    Regex rgx = new Regex("FROM\\s\\w+");
    MatchCollection matches = rgx.Matches(__query);

    /* output: 'tabela' */
    string table = matches[0].Value.Replace("FROM ", ""); 

    this.dAdapter.Fill(this.dSet, table);

    return this.dSet;
}

A utilização de um DataSet é bastante benéfico (em comparação com o DataReader) por várias razões:

  • Não é preciso que estabeleçamos uma ligação, pois o método .Fill() já faz isso;
  • Podemos de imediato atribuir o DataSource a um controlo (como é o caso da DataGridView);
  • É possível fazer queries dentro do DataSet, pois este guarda os dados como se de uma tabela se tratasse.

O leitor poderá verificar que foi incutido nesta função o uso das expressões regulares, que tem como aplicação devolver o nome da tabela da query. Não é obrigatório a utilização deste método, o nome da tabela pode ser passado via parâmetro (para a função) se assim preferir.

public int set(string __query, [Optional] MySqlParameter[] __param)
  { 
    this.command = new MySqlCommand(__query, this.connection);

    if (__param != null) { command.Parameters.AddRange(__param); }
 
    if (this.connection.State != ConnectionState.Open) { 
        this.connection.Open(); 
    }

    return this.command.ExecuteNonQuery(); 
    // retorna o número de linhas afectadas
}

Sim, a função set() contém apenas este trecho de código. Por precaução é retornado o número de linhas afectadas para perceber se foi ou não executado com sucesso.

A nossa classe está concluída. A classe executa eficazmente os métodos estipulados pelo CRUD de forma segura e muito simples. Resta agora colocar esta classe em acção.