Introdução

Atualmente, grande parte dos desenvolvedores de software trabalha com aplicações que manipulam banco de dados relacionais, utilizando a linguagem SQL.

A linguagem SQL (Structured Query Language) ou Linguagem de Consulta Estruturada nasceu nos laboratórios da IBM na década de 70, e é a linguagem padrão para se trabalhar com bancos de dados relacionais.

A linguagem SQL pode ser dividida em vários subconjuntos, que são definidos de acordo com as operações que realizam. Podemos dividir a linguagem SQL em:

  • DDL (Data Definition Language) – É o subconjunto responsável pela definição dos dados. O subconjunto DDL é utilizado para criar, alterar, e excluir tabelas em nossos bancos de dados, utilizando comandos como CREATE, ALTER, e DROP.
  • DML (Data Manipulation Language) – É o subconjunto responsável pela manipulação dos dados. O DML é utilizado para selecionar, inserir, atualizar, e deletar dados, utilizando comandos como SELECT, INSERT, UPDATE, e DELETE.
  • DCL (Data Control Language) – Subconjunto responsável pelo controle e autorização de acesso a dados, onde são utilizados comandos como: GRANT, REVOKE, e SET.

Os subconjuntos mais utilizados pelos desenvolvedores de software são DML e DDL, pois além de escrever rotinas para manipulação de dados (DML), muitos desenvolvedores também são responsáveis pela criação, alteração, e exclusão de tabelas em bancos de dados (DDL).

Durante a manipulação de um banco de dados, podem ocorrer falhas de hardware e/ou software, causando perda de dados. Para manipular os dados de forma segura e consistente, os sistemas gerenciadores de bancos de dados implementam o conceito de Transação.

Uma transação é um conjunto de alterações em um banco de dados que são executadas de maneira única. Para executar uma transação, os SGBDs obedecem a um conjunto de regras conhecidas com ACID, que visam proteger o banco de falhas e inconsistências.

Descrição das regras ACID:

  • Atomicidade – As operações de uma transação só serão persistidas (COMMIT) se todas elas forem executadas com sucesso. Caso ocorram falhas, todas as operações da transação serão canceladas (ROLLBACK).
  • Consistência – As transações devem respeitas as regras de integridade do banco, como chaves primárias, chaves estrangeiras, dentre outras, persistindo apenas dados válidos.
  • Isolamento – Uma transação não pode sofrer interferências de transações concorrentes.
  • Durabilidade – Quando uma transação é confirmada (COMMIT) os dados serão persistidos no banco, e podem ser recuperados.
Transações utilizando ADO.NET:

A plataforma .NET conta com um framework extremamente poderoso para lidar com o acesso e a manipulação de dados, o ADO.NET.

Para estudar controle de transações utilizando estas tecnologias, iremos utilizar separação de camadas com DAO Pattern.

Para este artigo foi utilizado o Visual Studio Express 2012, e o SQL Server 2012 acessando uma instância LocalDB.

Criação do Projeto:

Listagem 1: Script para do Banco de Dados


CREATE TABLE Contatos(
codigo INT NOT NULL,
nome NVARCHAR(50) NOT NULL,
email NVARCHAR(50),
telefone NVARCHAR(10),
CONSTRAINT PK_USUARIOS PRIMARY KEY (codigo)
)

Utilizando o Visual Studio, crie uma nova Windows Forms Application.

Adicione no formulário da aplicação os seguintes controles:

  • 05 controles do tipo Label
  • 03 controles do tipo TextBox
  • 01 controle do tipo MasktedTextBox (configurado para um campo Telefone)
  • 02 controles do tipo Button

Organize os controles, e altere a propriedade Text dos controles conforme a figura abaixo:

Disposição dos controles no formulário

Figura 1: Disposição dos controles no formulário

Altere o nome dos controles da seguinte forma:

  • txbCodigo
  • txbNome
  • txbEmail
  • mtbTelefone
  • btnInserir
  • btnGravar

Observação: Altere a propriedade TextMaskFormat do controle MaskedTextBox para "ExcludePromptAndLiterals", para não gravar a máscara no banco.

Adicione uma nova Class ao projeto, como o nome de ContatosMODEL, e implemente o código a seguir:

Listagem 2: Implementação dos métodos getters and setters da Classe ContatosMODEL


class ContatosMODEL
    {
        // Getters and Setters
        public int codigo { get; set; }
        public string nome { get; set; }
        public string email { get; set; }
        public string telefone { get; set; }
    }

Adicione uma nova Class, com o nome de ContatosDAO, e implemente o método a seguir:

Na classe ContatosDAO, não esqueça de adicionar os seguintes Namespaces:

  • using System.Data.SqlClient;
  • using System.Windows.Forms;
  • using System.Data;

Listagem 3: Método Gravar da Classe ContatosDAO


// método Gravar passando um objeto ContatosMODEL como parametro
 public void Gravar(ContatosMODEL contato)
       {
     // cria um objeto para conexão. Perceba que estou utilizando uma instância LocalDB do SQL Server
      SqlConnection conn = new SqlConnection(@"Server =(LocalDB)\v11.0;Database = banco;   Integrated Security = SSPI;");
     // cria objeto para controlar a transação
   SqlTransaction transacao;

           // abre a conexão;
           conn.Open();
          
           // inicia a transação
           transacao = conn.BeginTransaction(IsolationLevel.ReadCommitted);
           try
           {
              // objeto sql recebe uma instrução SQL, o objeto conn, e o objeto transacao
               SqlCommand sql = new SqlCommand("Insert Into contatos (codigo, nome, " + 
                                               "email, telefone) Values (@codigo, " +
                                               "@nome, @email, @telefone)", conn, transacao);
               
               // parametros da instrução sql
               sql.Parameters.AddWithValue("@codigo", contato.codigo);
               sql.Parameters.AddWithValue("@nome", contato.nome);
               sql.Parameters.AddWithValue("@email", contato.email);
               sql.Parameters.AddWithValue("@telefone", contato.telefone);
               sql.ExecuteNonQuery();  // executa a instrução no banco
               transacao.Commit();  // commita a transação
               conn.Close();   // fecha a conexao
           }
           catch (SqlException ex)
           {
               // Em caso de erros cancela (Rollback) a transação
               transacao.Rollback();
               MessageBox.Show(ex.Message); // mensagem contendo a SqlException
           }
       }

Voltando ao formulário, implemente o seguinte código no Evento Click do button btnInserir:

Listagem 4: Evento Click do button btnInserir


 private void btnInserir_Click(object sender, EventArgs e)
  {
        txbCodigo.Clear();
        txbNome.Clear();
        txbEmail.Clear();
        mtbTelefone.Text = "";
        txbCodigo.Focus();
    }

Implemente o seguinte código no Evento Click do button btnGravar:

Listagem 5: Evento Click do button btnGravar


 private void btnGravar_Click(object sender, EventArgs e)
     {
         // verifica campos em branco
         if (("".Equals(txbCodigo.Text)) | ("".Equals(txbNome.Text)))
         {
             MessageBox.Show("Verifique campos em branco","Contatos", 
                               MessageBoxButtons.OK, MessageBoxIcon.Error);
         }
         else
         {  
            ContatosMODEL contatosMODEL = new ContatosMODEL();
            ContatosDAO contatosDAO = new ContatosDAO();
            contatosMODEL.codigo = Convert.ToInt32(txbCodigo.Text);
            contatosMODEL.nome = txbNome.Text;
            contatosMODEL.email = txbEmail.Text;
            contatosMODEL.telefone = mtbTelefone.Text;
            contatosDAO.Gravar(contatosMODEL);
         }
     }

Conclusão

Nesse artigo aprendemos a implementar um controle de transações utilizando ADO.NET e C#.

Teste o código, refatore, e use a criatividade para implementar outros métodos, como consulta, atualização, delete, etc.

Um abraço.