ADO.NET: DataReader e Transações

Neste artigo trabalharei dois outros objetos muito importantes no ADO.Net, o DataReader e o Transaction, responsáveis pela leitura de dados no banco e pela ACID (Atomicidade, Consistência, Isolamento, Durabilidade) na manipulação de dados repectivamente.

Quando se espera o resultado de uma consulta SQL com mais de uma célula, pode ser utilizado objetos DataReader como forma de executar uma consulta no banco de dados retornando gradualmente o resultado, mantendo a conexão com o banco de dados até que a conexão seja encerrada.

DataReader: Recomendado em situações onde há a necessidade de ler o resultado de uma consulta. Abaixo dois exemplos típicos de como realizar consultas com o DataReader:

//Consulta de várias linhas.
Dictionary<int, string> dic = new Dictionary<int, string>();
string queryString = "SELECT id, nome FROM pessoa";
using (SqlConnection connection = new SqlConnection(connectionString))
{
  connection.Open();
  SqlCommand command = new SqlCommand(queryString, connection);
  using (SqlDataReader reader = command.ExecuteReader())
  {
    while (reader.Read())
    {
      dic.Add((int)reader[0], (string)reader[1]);
    }
  }
}
return dic;
//Consulta de uma única linha
string result = string.Empty;
string queryString = "SELECT id, nome FROM pessoa";
using (SqlConnection connection = new SqlConnection(connectionString))
{
  connection.Open();
  SqlCommand command = new SqlCommand(queryString, connection);
  using (SqlDataReader reader = command.ExecuteReader())
  {
    if (reader.Read())
    {
      result = String.Format("{0} - {1}", reader[0], reader[1]));
    }
  }
}
return result;

Visto a dependência da conexão com o banco de dados, o DataReader pode ser adaptado para fechar a conexão automaticamente ao finalizar a leitura, utilizando “CommandBehavior.CloseConnection”.

//Consulta de uma única linha
string queryString = "SELECT id, nome FROM pessoa";
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
SqlCommand command = new SqlCommand(queryString, connection);
return command.ExecuteReader(CommandBehavior.CloseConnection);

O DataReader pode retornar mais de uma consulta, que pode ser acessada facilmente com o método NextResult:

//Consulta de várias linhas
Dictionary<int, string> dic = new Dictionary<int, string>();
string queryString = "SELECT id, nome FROM pessoa1;\n"
  + "SELECT id, nome FROM pessoa2;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
  connection.Open();
  SqlCommand command = new SqlCommand(queryString, connection);
  using (SqlDataReader reader = command.ExecuteReader())
  {
    while (reader.Read())
    {
      dic.Add((int)reader[0], (string)reader[1]);}
      reader.NextResult();
      while (reader.Read())
      {
        dic.Add((int)reader[0], (string)reader[1]);
      }
    }
  }
}
return dic;

ou

//Consulta de várias linhas
Dictionary<int, string> dic = new Dictionary<int, string>();
string queryString = "SELECT id, nome FROM pessoa1;\n"
  + "SELECT id, nome FROM pessoa2;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
  connection.Open();
  SqlCommand command = new SqlCommand(queryString, connection);
  using (SqlDataReader reader = command.ExecuteReader())
  {
    do
    {
      while (reader.Read())
      {
        dic.Add((int)reader[0], (string)reader[1]);
      }
    } while(reader.NextResult());
  }
}
return dic;

Transaction: Para situações onde é necessário inserir ou alterar muitos registros no banco de dados de uma só vez e desfazer estas inserções ou alterações caso ocorra algum erro, é recomendado o uso de transação (Transaction).

Conforme o exemplo abaixo, é aberta uma conexão e criada uma transação pelo método “BeginTransaction”. Dentro da transação são executados dois métodos de inserção, caso algum deles dê erro será executado o método “RollBack” que desfará as inserções no banco de dados. Caso não haja erro, será necessário executar o método “Commit” para que as inserções tenham efeito.

using (SqlConnection connection = new SqlConnection(connectionString))
{
  connection.Open();
  using (SqlTransaction transaction = connection.BeginTransaction())
  {
    SqlCommand command = connection.CreateCommand();
    command.Connection = connection;
    command.Transaction = transaction;
    try
    {
      command.CommandText = "INSERT INTO tabela VALUES ('valor')";
      command.ExecuteNonQuery();
      command.CommandText = "INSERT INTO tabela VALUES ('valor')";
      command.ExecuteNonQuery();
      transaction.Commit();
    }
    catch
    {
      transaction.Rollback();
    }
  }
}

Transações não possuem “segredo”, são simples de serem utilizadas, mas em compensação, a execução dos comandos SQL podem demorar um pouco mais, afim de garantir atomicidade, consistência, isolamento, durabilidade do que esta sendo executado. Mas não se preocupe com situações simples, como a execução de um único comando de delete, insert ou update, pois o SQL Server possui transações implícitas nestes comandos, para evitar situações como alterar, deletar ou inserir “pela metade”.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s