ADO.NET - Salvando e recuperando imagens de um banco de dados - 2
No artigo - ADO.NET - Criando um cadastro de clientes - criamos uma pequena aplicação para gerenciar os dados dos clientes em uma base de dados Access. Que tal armazenar no banco de dados a foto do cliente de forma que a poder exibí-la no formulário em um controle PictureBox ? É isto que vamos fazer.
Podemos armazenar as imagens diretamente no banco de dados ou podemos optar por guardar somente a referência a imagem. Você deve considerar bem qual solução vai adotar pois cada uma tem suas vantagens e desvantagens.
Guardar a referência da imagem no banco de dados é mais simples em termos de código e tem a vantagem de ocupar muito menos espaço do seu banco de dados. Você cria um campo no banco de dados onde guarda o caminho e o nome da imagem . Para exibir a imagem basta recuperar o caminho e nome da imagem exibindo-a em um controle PictureBox. A desvantagem é que você terá que gerenciar a localização das imagens externamente a sua aplicação.
Nota: No VB.NET não existe mais o controle Image . Temos somente o controle PictureBox que agora suporta também arquivos GIF animados. Muitas de suas propriedades mudaram e outras não existem mais. Se você quiser consumir menos recursos pode sobrepor o evento OnPaint do formulário e usar o método DrawImage para exibir uma imagem. |
Armazenando as imagens no seu banco de dados você não precisa se preocupar com sua localização mas o código para salvar e recuperar uma imagem é mais complexo e você terá que considerar que o tamanho do seu banco de dados será bem maior. No caso de um banco de dados Access isto pode ser um fator limitante que você deverá considerar pois o tamanho máximo que um banco de dados Access pode chegar é algo em torno de 2 GB.
No artigo - Salvando imagens em um banco de dados - eu mostro uma outra forma de gravar imagens em um banco de dados |
Vou adotar a segunda solução e armazenar e recuperar as imagens diretamente no banco de dados. Para isto vou usar o aplicativo cadastro de clientes já criado e o banco de dados Biblio.mdb com a tabela Clientes. Então vamos arregaçar as mangas....
A primeira coisa a faze é alterar a estrutura do banco de dados e incluir um campo para armazenar as fotos dos clientes. Vou incluir um novo campo com o nome de Foto e do tipo Objeto OLE pois iremos armazenar dados no formato binário.(Você pode armazenar imagens , arquivos de áudio , etc.) Veja ao lado como deve ficar a estrutura da tabela Clientes.
|
Vamos agora alterar o layout do formulário incluindo um controle PictureBox para poder exibir as fotos dos clientes. Vou incluir um control Button (o antigo commandButton do VB6) para poder gerenciar a inclusão da imagem e um controle GroupBox (o antigo controle Frame do VB6). Abaixo o novo layout do formulário para cadastro de clientes:
- Ao lado o
novo layout do formulário já com os controles :
PictureBox , Button e GroupBox. - Vou dar um nome mais sugestivo para o controle PictureBox : picFoto e para o botão : btnIncluiImage - Teremos que alterar as configurações dos objetos odaClientes e dsClientes para refletir a nova estrutura da tabela Clientes. |
Vamos ter que ajustar as configurações dos objetos DataAdapter(odaClientes) e DataSet(dsClientes) pois a estrutura do banco de dados foi alterada e teremos que refletir esta alteração nestes objetos.
|
Vamos agora gerar novamente o DataSet.
Clique com o botão direito do mouse sobre o objeto odaClientes
Selecione a opção - Generate DataSet
Na janela - Generate DataSet - clique no botão OK e confirme a sobreposição do DataSet anterior.
Pronto ! as configurações já estão ajustadas para nova estrutura da tabela clientes.
Nota: Quando um dataset tipado é gerado em tempo de desenho (todos os DataSets gerados a partir de um DataAdapter são tipados por padrão) uma classe DataSet e um esquema XML associado é criado no seu projeto. Um esquema XML define e valida os dados importados de um fluxo XML ou documentos em um dataset tipado. O esquem XML associado com o dataset pode ser carregado em um Descritor XML fornecendo uma representação visual da estrutura do DataSet que pode se editado e visualizado. Veja na janela Solution Explorer o esquema XML - dsClientesx.xsd.(ver figura 1.0). Este arquivo é criado automaticamente para o novo dataset dsClientes. Se você clicar duas vezes sobre o arquivo dsClientesx.xsd o descritor XML irá exibir a estrutura do esquema XML (figura 2.0) Para visualizar o formato XML clique na guia XML e você terá estrutura do arquivo de esquema XML. (figura 3.0 ).
Um arquivo de esquema XML tem as seguintes funções:
Obs: Não altere nada na estrutura do arquivo XML. |
Vamos passar agora para a etapa onde iremos criar o código para exibir as fotos no formulário e salvar as imagens no banco de dados. Lembre-se que ainda não temos nenhuma imagem salva no banco de dados.
O botão incluir - btnIncluiImage -colocado abaixo do controle - PictureBox -picFoto - irá permitir que uma imagem seja salva no banco de dados. Este botão somente poderá estar habilitado quando o usuário estiver editando ou incluindo um novo registro, por isso , devemos definir a sua propriedade Enabled como False e torná-la True somente quando o usuário clicar nos botões Editar e Incluir. (Quando o usuário clicar nos botões Salvar e Cancelar devemos retornar Enabled como False)
Quando o usuário clicar no botão - Incluir - deveremos abrir uma caixa que permita a procura e seleção de um arquivo imagem a ser incluído no banco de dados. O controle - OpenFileDialog - faz exatamente isto , e , para simplificar vou usar um filtro para que somente imagens do tipo JPG sejam permitidas na seleção. Abaixo o código atribuido ao evento Click do botão - Incluir :
Private
Sub
btnIncluiImage_Click(ByVal
sender As System.Object, ByVal e
As System.EventArgs) Handles
btnIncluiImage.Click 'Permite somente arquivos Jpeg files OpenFileDialog1.Filter = "(Jpeg Files) *.jpg | *.jpg" OpenFileDialog1.Title = "Selecione um arquivo JPG para inserir no campo Foto" OpenFileDialog1.ShowDialog() If OpenFileDialog1.FileName <> "" Then 'Copia o arquivo jpeg selecionado para a PictureBox com o metodo FromFile do objeto Image picFoto.Image = Image.FromFile(OpenFileDialog1.FileName) End If End Sub |
Abaixo temos a janela - OpenFileDialog - filtrando apenas arquivos JPG sendo exibida. Observe que definimos a propriedade - Title - do componente para exibir o título da janela.
Após selecionar uma imagem a mesma deverá ser exibida no controle Picture Box e , se o usuário clicar no botão - Salvar - a imagem deverá ser salva no DataSet. O código associado ao evento Click do botão - Salvar - é dado a seguir:
Nota: Nas versões anterioes do VB o componente OLE Container permitia que você incluisse objetos OLE em seus formulários. No VB.NET os Windows Forms não suportam este recurso. Se precisar fazer isto use um controle WebBrowser. |
Private
Sub
btnsalvar_Click(ByVal
sender As System.Object, ByVal e
As System.EventArgs) Handles
btnsalvar.Click
'O método EndCurrentEdit do objeto BindingContext completa o processo de edição Me.BindingContext(dsClientes, "Clientes").EndCurrentEdit()
'Usei o método HasChanges do Dataset para estar certo de que o registro foi modificado antes ' de gastar recursos efetuando um Update na fonte de dados. HasChanges retorna True se ' alguma modificação foi feita. If dsClientes.HasChanges() = True Or OpenFileDialog1.FileName <> "" Then'Esteja certo que o usuario alterou o valor do PictureBox antes de atualizar o campo Foto If OpenFileDialog1.FileName <> "" Then 'Cria um objeto FileStream object e abre o arquivo imagem Dim fsPicFile As New System.IO.FileStream(OpenFileDialog1.FileName, System.IO.FileMode.Open, System.IO.FileAccess.Read)'Cria um Byte array vazio do tamanho do arquivo imagem Dim bytePicFile(fsPicFile.Length() - 1) As Byte'Usa o objeto FileStream (fsFicFile) para ler a imagem no Byte array fsPicFile.Read(bytePicFile, 0, bytePicFile.Length) 'Fecha FileStream fsPicFile.Close() 'Copia o conteudo do byte array (bytePicFile) para o campo Foto dsClientes.Clientes(Me.BindingContext(dsClientes,"Clientes").Position)("Foto") = bytePicFile 'Limpa a propriedade FileName depois de copiar a imagem jpeg para o campo Foto OpenFileDialog1.FileName = "" End If 'Para escrever as alterações de um registro para o banco de dados você deve chamar o método Update do DataAdapter odaClientes.Update(dsClientes) 'Após editar um registro você precisa preencher o Data Adapter novamente. Antes de fazer isto sempre limpe o Data Adapter dsClientes.Clear() 'O método Fill do Data Adapter preenche todos os datasets vinculados a ele odaClientes.Fill(dsClientes, "Clientes") End If txtNome.ReadOnly = True txtEndereco.ReadOnly = True txtUF.ReadOnly = True txtNascimento.ReadOnly = True txtTelefone.ReadOnly = True btnIncluiImage.Enabled = False SetButtons(sender, e) End Sub |
Agora só falta o código para recuperar uma imagem salva no campo Foto e exibí-la no controle - PicFoto -. Vamos criar uma rotina chamada MostraFoto() cujo código é o seguinte :
Private Sub MostraFoto()'tenha certeza de que a tabela contem registros If dsClientes.Tables("Clientes").Rows.Count > 0 Then'verifique se o campo Picture do registro atual não é NULL If Not dsClientes.Clientes(Me.BindingContext(dsClientes, "Clientes").Position)("Foto") Is DBNull.Value Then 'Dimensiona uma varivael Byte array (bytePicData) e armazena o valor no campo Foto Dim bytePicData() As Byte = _dsClientes.Tables("Clientes").Rows(Me.BindingContext(dsClientes, "Clientes").Position)("Foto")
'Um MemoryStream é um obejto System.IO (como um FileStream). Movendo os valores de ' do byte array bytePicData para MemoryStream, podemos usar o metodo FromStream do objeto Image Intrínseco ' para converter e copiar a figura diretamente para a propriedade Image do controle picFoto Dim PicMemStream As New System.IO.MemoryStream(bytePicData) picFoto.Image = Image.FromStream(PicMemStream) Else 'Se o campo Foto for Null, define a propriedade Image de picFoto para Nothing ' para remover qualquer imagem exibida antes picFoto.Image = Nothing End If End If End Sub |
Como devemos exibir as fotos para cada cliente a rotina - MostraFoto() - deverá ser invocada sempre que irmos de um registro para outro. Vamos então colocar a chamada para a rotina na procedure - SetButtons().
Pronto ! agora é só executar o projeto , salvar algumas imagens e ver o resultado final . (abaixo um exemplo):
O próximo passo será incluir uma rotina para procurar informações em nosso projeto. Aguarde...
(O código completo deste artigo esta no Super DVD .Net.)
Veja os
Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique
e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ?
|
Gostou ?
Compartilhe no Facebook
Compartilhe no Twitter
Referências: