segunda-feira, 7 de junho de 2010

Conectando a um banco de dados MySQL com C#

Bom. Primeiro você precisará baixar e instalar o MySql Connector Net, para usar MySQL no Visual Studio.
    Link:
    http://dev.mysql.com/downloads/connector/net/6.1.html

Segundo. Será necessário um servidor MySQL.
    XAMPP
    http://www.baixaki.com.br/download/xampp.htm

Sempre que precisar conectar ao banco de dados você deverá estar com o xampp em execução e o MySQL do xampp iniciado (conforme a imagem). Para iniciar ele é só clicar no "Start" ao lado do MySQL.


Agora ao que interessa.
Na Solution Explorer do programa em que pretende utilizar o banco de dados, clique com o botão direito do mouse em 'References' e então clique em 'Add Reference'.


Abrirá uma nova janela. Na aba '.NET' ache o componente 'MySql.Data' selecione-o e então clique OK.


Feito isso adicione o namespace no início do programa utilizando a instrução 'using'.
Exemplo:
using System;
using System.Text;
using System.Collections.Generic;
using MySql.Data.MySqlClient;\\ <====

Feito isso vamos aos atributos.


Na minha classe eu criei os objetos relacionados ao MySql (já explico melhor...) e atributos para armazenar servidor, nome do banco de dados, usuario e senha (necessários para a conexão), além de uma struct Tabela para servir como modelo para as minhas tabelas.
Exemplo:

public class Nome_da_classe
{
    /*Primeiro os atributos relacionados com o MySQL*/
    private MySqlConnection conexao;/*Objeto utilizado para fazer a conexão com o banco de dados.*/
    private MySqlCommand comando;/*Objeto onde se coloca o comando para ser executado no banco de dados.*/

    private string _servidor;/*Armazenará o servidor para conexão.*/
    private string _nomeBD;/*Armazenará o nome do Banco de Dados.*/
    private string _usuario;/*Armazenará o usuário.*/
    private string _senha;/*Armazenará a senha.*/

    private struct Tabela /*Declarando struct Tabela.*/
    {
        public string nome;
        public List<string> campos;
    }

    private List<Tabela> _tabelas = new List<Tabela>();/*Cria uma lista de tabelas.*/
}

No construtor será preciso inicializar esses atributos.
No meu caso criei 2 construtores.

public class Nome_da_classe
{
.
.
.
    /*Este construtor inicializa os atributos com strings padrão e cria um nome qualquer para o banco de dados.*/
    public Nome_da_classe()
    {
        _servidor = "localhost";/*É o mesmo que colocar "127.0.0.1". Isso criará um banco de dados local.*/
        _nomeBD = "meubancodedados";
        _usuario = "root";
       _senha = "''";/*A senha está recebendo um caracter vazio. É apenas por uma questão de visualização, mas na prática é a mesma coisa que _senha = "";*/
       conexao = new MySqlConnection("SERVER=" + _servidor + "; DATABASE=" + _nomeBD + "; UID=" + _usuario + "; PASSWORD=" + _senha);
       /*Instanciei o MySqlConnection, passando a 'connection string' por parâmetro. No caso ele irá conectar-se ao banco de dados utilizando a seguinte 'string
connection': "SERVER=localhost; DATABASE=meubancodedados; UID=root; PASSWORD=''"*/
       comando = new MySqlCommand("", conexao);
       /*Instanciei o MySqlcommand passando para ele uma string vazia, que é o comando a ser executado (mostrarei que isso pode ser modificado depois) e um objeto MySqlConnection.*/
    }

    /*Este construtor permite conectar a qualquer banco de dados da rede passando as informações por parâmetro.*/
    public Nome_da_classe(string servidor, string nomeBD, string usuario, string senha)
    {
        /*Apenas testa se a string não está vazia, e se ela estiver coloca o valor padrão em _servidor.*/
        if (!servidor.Equals(""))
            _servidor = servidor;
        else _servidor = "localhost";
        /*Apenas testa se a string não está vazia, e se ela estiver coloca o valor padrão em _nomeBD.*/
        if (!nomeBD.Equals(""))
            _nomeBD = nomeBD;
        else _nomeBD = "meubancodedados";
        /*Apenas testa se a string não está vazia, e se ela estiver coloca o valor padrão em _usuario.*/
        if (!usuario.Equals(""))
            _usuario = usuario;
        else _usuario = "root";
        /*Apenas testa se a string não está vazia, e se ela estiver coloca o valor padrão em _senha.*/
        if (!senha.Equals(""))
            _senha = senha;
        else _senha = "''";
        conexao = new MySqlConnection("SERVER=" + _servidor + "; DATABASE=" + _nomeBD + "; UID=" + _usuario + "; PASSWORD=" + _senha);
        comando = new MySqlCommand("", conexao);
    }
.
.
.
}


Bom, agora alguns métodos.
Eu preciso criar um método para conectar ao banco de dados e outro para desconectar.
Mas antes eu vou criar um método para criar um banco de dados. Depois eu explico o porquê.

public class Nome_da_classe
{
.
.
.
    public void CriarBD()
    {
        conexao = new MySqlConnection("SERVER=" + _servidor + "; DATABASE=; UID=" + _usuario + "; PASSWORD=" + _senha);
        /*Eu instanciei o MySqlConnection com uma string sem o nome do banco de dados. Isso fará com que ele conecte-se apenas ao servidor.*/
         try
        {
            conexao.Open();
            try
            {
                /*Cria um MySqlCommand com uma string de comando de criação de banco de dados com o nome que está armazenado no atributo 'nomeBD'.*/
                MySqlCommand cmd = new MySqlCommand("CREATE DATABASE `" + _nomeBD + "` ;", conexao);
                cmd.ExecuteNonQuery();//Executa o comando.
            }
            catch (MySqlException) { }
        }
        catch (MySqlException) { }
    }

    //Agora os métodos para conectar e desconectar.

    public void Conectar()
    {
        if (!(conexao.State == ConnectionState.Open))
        {/*A propriedade State retorna um tipo 'enumerator' que representa o estado da conexao.
          Este 'if' testa se a conexão não está ativa e só entra no laço se a conexão não estiver ativa.*/
            try
            {
                conexao.Open();/*Tentará conectar ao banco de dados com a string.*/
            }
            catch (MySqlException) { }
        }


        if (!(conexao.State == ConnectionState.Open))
        {//Esse teste é igual ao anterior.
        /*Pode ocorrer de ele não ter conseguido conectar ao banco de dados pelo fato de o banco de dados não existir ainda. Então agora ele tenta criar o banco de dados. OBS.: Por isso eu quis fazer o método de criar um banco de dados antes. Agora eu só preciso chamá-lo.*/
            CriarBD();
            /*Criado o banco de dados, tenta conectar novamente.*/
            conexao = new MySqlConnection("SERVER=" + _server + "; DATABASE=" + _bancodedados + "; UID=" + _usuario + "; PASSWORD=" + _senha);
            try
            {
                conexao.Open();
            }
            catch (MySqlException) { }
             if (conexao.State == ConnectionState.Open)
                comando = new MySqlCommand("", conexao);
        }
    }

    public void Desconectar()
    {
        try
        {
            conexao.Close();
        }
        catch (MySqlException) { }
    }
.
.
.
}


Essa não é a forma como eu fiz na minha classe. É uma forma simplificada para uso geral.
O mesmo vale para os métodos de inserção de tabelas e valores que eu vou mostrar a seguir.

public class Nome_da_classe
{
.
.
.
    public void CriarTabela(string nometabela, string[] campos)
    {
        if (conexao.State == ConnectionState.Open)
        {
            Tabela tabela = new Tabela();
            tabela.nome = nometabela;
            tabela.campos = new List<string>();
            _tabelas.Add(tabela);
            foreach (string s in campos)
                _tabelas.Last().campos.Add(s);
            comando.CommandText = "CREATE TABLE `" + _nomeBD + "`.`" + _tabelas.Last().nome + "` (";
            /*A propriedade CommandText armazena apenas a string que representa o comando que será executado.
            Utilizando essa propriedade não é necessário instanciar o atributo 'comando' toda vez que quiser executar um novo comando.
            Apenas modifique essa propriedade antes de usar método ExecuteNonQuery();*/


            foreach (string s in campos)
                comando.CommandText += "`" + s + "`" + "INT(255) NOT NULL,";/*Insere os campos com ',' depois.*/
            comando.CommandText = comando.CommandText.TrimEnd(',') + ") ENGINE = INNODB;";
            /*Se a inserção dos campos for feita da forma
            mostrada acima será necessário remover a
            última ',' utilizando o TrimEnd, como demostrando.*/
            try
            {
                comando.ExecuteNonQuery();
            }
            catch (MySqlException)
            {
                _tabelas.RemoveAt(_tabelas.Count() - 1);
            }
        }
    }

    public void InserirValores(string nometabela, string[] valores)
    {
        if (!(conexao.State == ConnectionState.Open))
        {
            comando.CommandText = "";


            foreach (Tabela t in _tabelas)
                if (t.nome.Equals(nometabela))
                {
                    comando.CommandText = "INSERT INTO `" + _nomeBD + "`.`" + nometabela + "` (";
                    foreach (string s in t.campos)
                        comando.CommandText += "`" + s + "`" + ", ";
                    comando.CommandText = comando.CommandText.TrimEnd(' ', ',') + ") ";
                }
            if (comando.CommandText.Equals(""))
            {/*Testa se a propriedade CommandText está com uma string vazia,
pois se ela estiver significa que nenhuma tabela com o nome recebido
por parâmetro foi encontrada. Eu uso isso para inserir na última tabela
criada, com o código abaixo.*/
                nometabela = _tabelas.Last().nome;
                comando.CommandText = "INSERT INTO `" + _nomeBD + "`.`" + nometabela + "` (";
                foreach (string s in _tabelas.Last().campos)
                    comando.CommandText += "`" + s + "`" + ", ";
                comando.CommandText = comando.CommandText.TrimEnd(',', ' ') + ") ";
            }
            comando.CommandText += "VALUES (";
            foreach (string s in valores)
                comando.CommandText += "'" + s + "', ";
            comando.CommandText = comando.CommandText.TrimEnd(',', ' ') + ");";
             try
            {
                comando.ExecuteNonQuery();
            }
            catch (MySqlException) { }
        }
    }

    public void AddCampo(string nometabela, string campo)
    {
        if (conexao.State == ConnectionState.Open)
        {
            comando.CommandText = "";
            foreach (Tabela t in _tabelas)
                if (t.nome.Equals(nometabela))
            comando.CommandText = "ALTER TABLE `" + nometabela + "` ADD `" + campo + "` INT(255) NOT NULL";
             if (comando.CommandText.Equals(""))
            {/*Este laço também adiciona na última tabela caso a string nometabela que veio por parâmetro esteja vazia. Da mesma forma que foi feito no método InserirValores().*/
                nometabela = _tabelas.Last().nome;
                comando.CommandText = = "ALTER TABLE `" + nometabela + "` ADD `" + campo + "` INT(255) NOT NULL";
            }
            try
            {
                comando.ExecuteNonQuery();
            }
            catch (MySqlException) { }
        }
    }

    public string LerValor(string nometabela, string campo, int linha)
    {
        string resposta = "";
        MysqlDataReader _leitura;
        comando.CommandText = "";
        if (conexao.State == ConnectionState.Open)
        {
            foreach (Tabela t in _tabelas)
                if (t.nome.Equals(nometabela))
            comando.CommandText = = "SELECT `" + campo + "` FROM `" + _nomeBD + "`.`" + nometabela + "` LIMIT " + linha + ",1";
            if (comando.CommandText.Equals(""))
            {
                nometabela = _tabelas.Last().nome;
                comando.CommandText = "SELECT `" + campo + "` FROM `" + _nomeBD + "`.`" + nometabela + "` LIMIT " + linha + ",1";
            }
            try
            {
                _leitura = comando.ExecuteReader();/*Nota. Agora não se usa o ExecuteNonQuery e sim o ExecuteReader. Além disso é necessário um MySqlDataReader para armazenar a informação para depois poder ler.*/


                if (_leitura.Read())
                    resposta = _leitura.GetValue(0).ToString();
                else resposta = null;
                _leitura.Close();
            }
            catch (MySqlException) { }
        }
        else resposta = "Não conectado.";
        return resposta;
    }
.
.
.
}

Era isso... abaixo os sites que foram úteis para mim.

Sites úteis:
http://www.macoratti.net/08/08/c_mysql1.htm
http://www.macoratti.net/08/09/c_mysql2.htm
http://imasters.uol.com.br/artigo/13681/mysql/conectando_c_ao_mysql/

Um comentário:

Anônimo disse...

Jovem aqui encontrei o jeito mais simples de aprender a conexão, mas ainda assim estou sentindo dificuldade de entender. Irei tentar utilizar seus ensinamentos com o apoiode um livro. Mas obrigado por postar cara.