.NET

12 nov, 2008

C# – Trabalhando com dados binários no SQL Server (DataReader)

Publicidade

O comportamento padrão do DataReader é obter os dados a partir da fonte linha por linha. Quando vamos trabalhar com dados binários (BLOB) usando o objeto DataReader, o tratamento deve ser um pouco diferente pois eles podem conter um grande volume de dados que não podem estar contidos em uma única linha.

O método Command.ExecuteReader possui uma sobrecarga que usa um argumento CommandBehavior para modificar este comportamento padrão do DataReader.

Você pode passar um CommandBehavior.SequentialAcces para o método ExecuteReader para modificar o comportamento padrão do DataReader, de forma que ao invés de carregar linhas de dados ele irá carregar os dados de forma sequencial conforme forem recebidos. Este é o tratamento ideal quando formos usar dados do tipo binário como os BLOB.

Usando SequentialAccess

A utilização do SequentialAccess permite que o DataReader carregue os dados como um fluxo de bytes (stream).

Ao definir a utilização do SequentialAccess, é importante notar a sequência na qual você irá acessar os campos que forem retornados.

O comportamento padrão do DataReader permite que você acesse os campos retornados em qualquer ordem até que a próxima linha seja lida. Quando você for usar o SequentialAccess você precisa acessar os diferentes campos retornados pelo DataReader na ordem correta.

[i]Ao usar um DataReader, se você for acessar os dados de forma sequencial (1o campo, 2o campo, etc…) , poderá aumentar o desempenho usando um commandBeheavior.SequentialAccess quando for utilizar o ExecuteReader. Fazendo assim o DataReader é avisado de que o acesso é sequencial e isso otimiza o acesso.

Os valores de CommandBehavior são usados pelo método ExecuteReader da interface IDbCommand e qualquer classe derivada dela. Exemplo de uso:[/i]

dr = cmd.ExecuteReader(CommandBehavior.SequentialAccess)

Assim, se a sua consulta retorna 3 colunas e a terceira é um campo do tipo BLOB, você deve retornar os valores do primeiro e do segundo campos antes de acessar os dados binários da terceira coluna. De outra forma os valores dos campos se tornam indisponíveis. Este comportamento é devido à alteração que o SequentialAcess realizou no DataReader para retornar os dados na sequência.

Quando acessar os dados em um campo do tipo BLOB você deve usar os tipos de acessos GetBytes ou GetChars que preenchem um array com dados.

Você até pode usar um GetString para dados do tipo caractere, porém, para conservar os recursos do sistema, você não pode carregar um valor BLOB em uma variável string. Você pode definir um buffer de dados com um determinado tamanho a ser retornado e iniciar a leitura partir do primeiro byte ou caractere a ser lido. GetBytes e GetChars retornam um valor do tipo long que representa o número de bytes ou caracteres retornados.Você também pode definir um índice no array indicando a posição e a ordem dos dados a serem lidos.

Escrevendo BLOBS

Para escrever dados binários para o banco de dados você deve usar o comando SQL apropriado INSERT ou UPDATE e passar o valor do BLOB com um parâmetro de entrada. Se o seu BLOB está armazenado como um texto(documento), você pode passar o BLOB como um parâmetro String. Se o BLOB está armazenado no formato binário como uma imagem, você pode passar um array de bytes como um parâmetro binário.

Abaixo temos um esquema simplificado do fluxo de atividades realizado para ler/gravar dados binário do tipo Image;

Vejamos a seguir um exemplo que inclui informação sobre funcionários na tabela Employees do banco de dados Northwind.

Uma foto do funcionário é lida a partir do arquivo e incluída no campo Photo na tabela que é um campo do tipo Image.

O campo Photo é então lido usando GetBybtes.

Note que o código do funcionário é acessado para a linha atual antes da foto, pois os campos precisam ser acessados de forma sequencial e na ordem.

Criando uma aplicação Windows Forms

Vamos criar uma aplicação Windows Forms usando o Visual C# Express Edition 2008 para incluir e acessar dados de uma tabela do SQL Server Express Edition.

Abra o Visual C# 2008 Express e crie uma nova aplicação Windows Application com o nome de usandoDadosBinarios;

A seguir inclua a partir da ToolBox os controles :

  • 1 PictureBox = picFoto;
  • 4 TextBox = txtNome, txtEndereco, txtCargo, txtAdmissao;
  • 4 Labels
  • 3 Button – btnCarregaFoto, btnIncluirDados, btnSelecionar;
  • 1 StatusStrip – barraStatus;

O layout do formulário deve ser parecido com o da imagem abaixo:

Vejamos primeiro o código relacionado a cada evento Click dos botões de comando:

1- Botão Carrega Foto:

void TbnCarregaFotoClick(object sender, EventArgs e)
{
            OpenFileDialog dlg = new OpenFileDialog();

            dlg.Title = "Abrir Foto";
            dlg.Filter = "JPG (*.jpg)|*.jpg"
                + "|All files (*.*)|*.*";

            if (dlg.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    picFoto.Image = new Bitmap(dlg.OpenFile());
                    foto = dlg.FileName;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Não foi possivel carregar a foto: " + ex.Message);
                }
            }

            dlg.Dispose();
}

Neste código abrimos uma caixa de diálogo OpenFileDialog para selecionar o arquivo a ser exibido no controle PictureBox – picFoto, conforme a figura acima mostra.

2- Botão Incluir Dados

void BtnIncluirDadosClick(object sender, EventArgs e)
{

               String nome = txtNome.Text;
               String endereco = txtEndereco.Text;
               String cargo = txtCargo.Text;
               DateTime admissao = DateTime.Parse("2008.11.04");

                IncluiFuncionario(nome,endereco,cargo,admissao,5,foto);

                barraStatus.Text = "Funcionário incluido no banco de dados";
}

Este código obtém os valores informados no formulário e chama a rotina para incluir um novo funcionário na tabela;

3- Botão Selecionar

void BtnSelecionarClick(object sender, EventArgs e)
{
	if (txtNome.Text.Equals(""))
	{
	    MessageBox.Show("Informe o nome do funcionário.");
	    return;
	}
	else
	{
	    GetFuncionario(txtNome.Text);
	}
			
            barraStatus.Text = "Arquivo Salvo no sistema";
}

Neste código vamos selecionar um funcionário através de seu nome usando a rotina getFuncionario();

Aguarde, na continuação deste artigo, o código para incluir e selecionar um funcionário.

Eu sei, é apenas C#, mas eu gosto…