André Alves de Lima

Talking about Software Development and more…

Salvando imagens no banco de dados utilizando C#

Uma dúvida recorrente entre programadores que estão iniciando no mundo do C# diz respeito a salvar imagens no banco de dados. Essa não é uma tarefa complicada, mas, devido à grande diversidade de maneiras de acessar o banco de dados no .NET, o desenvolvedor acaba ficando um pouco perdido. Após um dos inscritos na minha newsletter ter feito justamente essa mesma pergunta, resolvi que era hora de abordar esse assunto. Vamos conferir neste artigo algumas das maneiras de salvar imagens no banco de dados. Espero que alguma delas acabe te ajudando.

Como mencionado no parágrafo anterior, um dos motivos para que essa seja uma dúvida recorrente, é que existem diversas maneiras de resolver essa tarefa. Porém, em todas elas, um ponto que não se altera é o banco de dados. Portanto, o primeiro passo deste artigo mostrará a criação da tabela onde as imagens serão armazenadas.

Criando o banco de dados

Em um cenário “normal” de desenvolvimento, antes de começar a codificar, é bom parar para pensar na estrutura do banco de dados. Existem algumas tecnologias que permitem que você se “esqueça” do banco de dados e só se preocupe com a estrutura de classes da sua aplicação (como, por exemplo, o Entity Framework Code First). Na minha visão (pelo menos nas experiências que eu tive até hoje), na maioria das vezes, planejaremos o banco de dados antes de começarmos a programar. Portanto, não será abordada nenhuma tecnologia do tipo “Code First” neste artigo.

Como a ideia deste artigo é mostrar, da maneira mais simples possível, como salvar imagens no banco de dados, vamos criar uma tabela bem simples para armazenar algumas fotos. Vamos utilizar um banco de dados SQL Server Express (que você pode baixar gratuitamente – mais informações aqui) e criar essa tabela (que dei o nome de “Foto“) com somente três colunas: FotoID, Descricao e Foto.

Veja o script SQL para a criação dessa tabela:

CREATE TABLE [Foto] (
	[FotoID] [int] IDENTITY(1,1) NOT NULL,
	[Descricao] [varchar](200) NOT NULL,
	[Foto] [image] NOT NULL,
	CONSTRAINT [PK_Foto] PRIMARY KEY CLUSTERED ([FotoID] ASC)
)

Uma vez criada a tabela, vamos partir para a criação do exemplo.

Criando a aplicação de exemplo

Vamos utilizar um projeto do tipo “Windows Forms” simplesmente pelo motivo de essa ainda ser a tecnologia mais utilizada hoje em dia para desenvolvimento de aplicativos desktop com a plataforma .NET. Porém, as maneiras de salvar imagens no banco de dados que serão demonstradas neste artigo são independentes do Windows Forms, ou seja, você poderia tirar proveito dessas dicas mesmo se a sua aplicação estiver utilizando WPF.

A ideia básica é estender o artigo sobre fotos com a webcam no C# que foi publicado em Novembro de 2014. Portanto, após ter criado o projeto Windows Forms, ajuste o Form1 de forma que ele fique parecido com a imagem abaixo:

Seguindo o tutorial sobre webcam em C#, vamos implementar o suporte à webcam da seguinte maneira (confira maiores detalhes sobre as referências necessárias no artigo sobre webcam):

    public partial class FormFotoDB : Form
    {
        AForge.Video.DirectShow.VideoCaptureDevice videoSource;

        public FormFotoDB()
        {
            InitializeComponent();

            AForge.Video.DirectShow.FilterInfoCollection videosources = new AForge.Video.DirectShow.FilterInfoCollection(AForge.Video.DirectShow.FilterCategory.VideoInputDevice);

            if (videosources != null)
            {
                videoSource = new AForge.Video.DirectShow.VideoCaptureDevice(videosources[0].MonikerString);
                videoSource.NewFrame += (s, e) => webCamPictureBox.Image = (Bitmap)e.Frame.Clone();
                videoSource.Start();
            }
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);

            if (videoSource != null && videoSource.IsRunning)
            {
                videoSource.SignalToStop();
                videoSource = null;
            }
        }
    }

Além disso, vamos adicionar a string de conexão no arquivo de configurações da aplicação. Para isso, abra o arquivo “Settings.settings” e adicione a string de conexão como demonstrado nas imagens abaixo.

Feito isso, estamos prontos para adicionar o suporte à gravação das imagens no banco de dados. Iremos conferir nesse artigo três maneiras de implementar essa funcionalidade: utilizando ADO.NET puro (com DbConnection e DbCommand), utilizando um DataSet tipado (com DataAdapter embutido) e, finalmente, utilizando o Entity Framework.

Salvando a imagem com ADO.NET puro

Quando falamos de ADO.NET “puro”, estamos falando da utilização manual das classes básicas do ADO.NET (DbConnection, DbCommand, etc) juntamente com comandos SQL a fim de recuperarmos dados do banco de dados ou executarmos sentenças de INSERT ou DELETE diretamente no banco de dados.

Edit: em março de 2017 eu publiquei um vídeo mostrando um outro exemplo de como podemos salvar arquivos no banco de dados utilizando ADO.NET puro. Se você se interessar, aqui vai o vídeo:

Essa maneira de persistir dados é ao mesmo tempo a mais simples e a mais complicada. Ela é a mais simples pois não exige que tenhamos que adicionar nenhuma referência ao nosso projeto, nem exige que criemos outras classes adicionais para lidar com a persistência de dados (apesar de ser uma boa prática separar a camada de acesso a dados).

O primeiro ajuste que faremos no nosso projeto diz respeito ao carregamento da lista de fotos no controle “fotosDBListBox“. Para isso, vamos adicionar um método ao nosso Form que fará uma query buscando todos os registros da tabela “Foto” e armazenará todos esses registros retornados em uma DataTable. Após feito o carregamento, utilizaremos essa DataTable como DataSource da ListBox. Confira a implementação no método a seguir.

        private void CarregarThumbnailsAdoNet()
        {
            using (var connection = new System.Data.SqlClient.SqlConnection(Properties.Settings.Default.ExemploDBConnectionString))
            {
                try
                {
                    connection.Open();

                    if (connection.State == ConnectionState.Open)
                    {
                        using (var command = connection.CreateCommand())
                        {
                            command.CommandText = "SELECT * FROM Foto";
                            var dataReader = command.ExecuteReader();
                            DataTable dataTable = new DataTable();
                            dataTable.Load(dataReader);
                            fotosDBListBox.DataSource = dataTable;
                            fotosDBListBox.DisplayMember = "FotoID";
                            fotosDBListBox.ValueMember = "FotoID";
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Erro ao abrir conexão com o banco de dados.\n{0}", ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

Como podemos notar no código acima, para retornar todos os registros da tabela “Foto“, precisamos primeiramente criar e abrir uma conexão com o banco de dados. Utilizamos as classes do namespace System.Data.SqlClient pois o banco de dados utilizado nesse exemplo é o SQL Server. Caso você trabalhe com outro banco de dados, você precisará utilizar outro provider (por exemplo, “OleDb” para bancos Microsoft Access). Porém, a implementação será muito parecida, pois as classes dos providers específicos sempre herdam das classes base do .NET Framework.

O construtor de SqlConnection recebe como parâmetro a string de conexão (que criamos na seção anterior). Após abrir a conexão utilizando o método Open, precisamos conferir se a conexão foi realmente aberta. Para isso, utilizamos a propriedade State.

Uma vez criada e aberta a conexão, basta chamarmos o método CreateCommand para criar uma nova instância de SqlCommand, configurar a propriedade CommandText com a query SQL a ser executada e chamar o método ExecuteReader (pois nesse caso estamos lendo dados do banco). Com o DataReader em mãos, podemos criar a DataTable e chamar o método Load passando o DataReader. Finalmente, uma vez que a DataTable está preenchida, podemos utilizá-la como DataSource da ListBox, configurando as propriedades DataSource, DisplayMember e ValueMember.

Adicione uma chamada ao método “CarregarThumbnailsAdoNet” no final do construtor do Form e execute a aplicação de exemplo para conferir o resultado. Até o momento, como não temos nenhuma foto armazenada na tabela “Foto“, a ListBox aparecerá vazia.

Agora vamos ver como ficaria o código para salvar a imagem sendo exibida pela webcam no banco de dados utilizando o ADO.NET puro. Para isso, vamos criar dois novos métodos, chamados “SalvarFotoAdoNet” e “ConverterFotoParaByteArray“:

        private void SalvarFotoAdoNet()
        {
            using (var connection = new System.Data.SqlClient.SqlConnection(Properties.Settings.Default.ExemploDBConnectionString))
            {
                try
                {
                    connection.Open();

                    if (connection.State == ConnectionState.Open)
                    {
                        using (var command = connection.CreateCommand())
                        {
                            command.CommandText = "INSERT INTO Foto (Descricao, Foto) VALUES (@Descricao, @Foto)";
                            command.Parameters.AddWithValue("Descricao", DateTime.Now.ToString());
                            command.Parameters.AddWithValue("Foto", ConverterFotoParaByteArray());
                            command.ExecuteNonQuery();
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Erro ao abrir conexão com o banco de dados.\n{0}", ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private byte[] ConverterFotoParaByteArray()
        {
            using (var stream = new System.IO.MemoryStream())
            {
                webCamPictureBox.Image.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
                stream.Seek(0, System.IO.SeekOrigin.Begin);
                byte[] bArray = new byte[stream.Length];
                stream.Read(bArray, 0, System.Convert.ToInt32(stream.Length));
                return bArray;
            }
        }

Note que uma boa parte do código de “SalvarFotoAdoNet” é muito parecido com o que vimos anteriormente. A diferença é que, após criar o SqlCommand, nós temos que configurar a propriedade CommandText para uma sentença de INSERT. Como essa sentença utiliza parâmetros (para maiores informações sobre parâmetros no ADO.NET, confira este artigo) – @Descricao e @Foto – precisamos adicioná-los ao SqlCommand. Fazemos isso com o método AddWithValue, sendo que o primeiro argumento é o nome do parâmetro e o segundo argumento é o valor.

A grande sacada nesse ponto está no método “ConverterFotoParaByteArray“. Ao criar uma coluna do tipo “image” no SQL Server, precisamos passar o seu valor para o ADO.NET como um array de bytes. Isso pode ser facilmente realizado utilizando um MemoryStream, como pode ser observado no método “ConverterFotoParaByteArray“.

Finalmente, adicione um handler para o evento “Click” do botão “Click!” e, dentro desse handler, chame os métodos “SalvarFotoAdoNet” e “CarregarThumbnailsAdoNet“:

        private void clickButton_Click(object sender, EventArgs e)
        {
            SalvarFotoAdoNet();
            CarregarThumbnailsAdoNet();
        }

Execute a aplicação, salve algumas fotos no banco de dados utilizando o botão “Click” e veja que a ListBox é carregada com os IDs das fotos (que é um campo auto incremento). Porém, como fazer para que, ao selecionar um item na ListBox, o thumbnail seja exibido na PictureBox? É só implementar um handler para o evento SelectedIndexChanged da ListBox, conforme podemos conferir a seguir:

        private void fotosDBListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            var dataRowView = fotosDBListBox.SelectedItem as DataRowView;
            if (dataRowView != null)
            {
                using (var stream = new System.IO.MemoryStream((byte[])dataRowView.Row["Foto"]))
                {
                    thumbnailPictureBox.Image = Bitmap.FromStream(stream);
                }
            }
        }

Nesse handler, nós recuperamos o item selecionado na ListBox, convertemos para DataRowView e pegamos o valor da coluna “Foto“. O conteúdo dessa coluna é, como vimos anteriormente, um array de bytes. Para convertê-lo em imagem, basta criarmos um MemoryStream passando o array de bytes no construtor e, em seguida, utilizar esse MemoryStream no método FromStream da classe Bitmap.

Execute o aplicativo novamente e veja que, ao clicar em um item da ListBox, o thumbnail da imagem é exibido com sucesso. Mas, ainda está faltando o código para excluir a imagem. Como ficaria esse código? Confira logo abaixo no método “ExcluirFotoAdoNet“:

        private void ExcluirFotoAdoNet()
        {
            var dataRowView = fotosDBListBox.SelectedItem as DataRowView;
            if (dataRowView != null)
            {
                using (var connection = new System.Data.SqlClient.SqlConnection(Properties.Settings.Default.ExemploDBConnectionString))
                {
                    try
                    {
                        connection.Open();

                        if (connection.State == ConnectionState.Open)
                        {
                            using (var command = connection.CreateCommand())
                            {
                                command.CommandText = "DELETE FROM Foto WHERE (FotoID = @FotoID)";
                                command.Parameters.AddWithValue("FotoID", dataRowView.Row["FotoID"]);
                                command.ExecuteNonQuery();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Erro ao abrir conexão com o banco de dados.\n{0}", ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }

Novamente, boa parte do código é parecida com os códigos anteriores. A parte de criação e abertura da conexão, bem como a parte de criação do comando, é idêntica aos exemplos anteriores. Inclusive, uma boa prática seria extrair essa parte do código em um método para que não tenhamos que ficar repetindo o mesmo código várias vezes. Porém, vou pular esse passo, uma vez que esse não é o foco do artigo.

Finalmente, adicione um handler para o evento “Click” do botão “Excluir” conforme o código a seguir:

        private void excluirButton_Click(object sender, EventArgs e)
        {
            ExcluirFotoAdoNet();
            CarregarThumbnailsAdoNet();
        }

Agora sim, o exemplo utilizando ADO.NET puro está completo. Execute a aplicação e teste todas as etapas: criação das imagens, exibição das imagens no thumbnail e exclusão das imagens.

Salvando a imagem com DataSet tipado

Uma forma um pouco mais simples de salvar a imagem seria utilizando DataSets tipados. Com eles, o Visual Studio cria automaticamente DataAdapters que tornam a nossa vida muito mais fácil. O primeiro passo é criarmos um DataSet tipado contendo a tabela “Foto“. Para isso, adicione ao projeto um novo item do tipo “DataSet” (no exemplo abaixo utilizamos o nome de FotoDataSet):

Feito isso, abra o Server Explorer (menu View => Server Explorer) e adicione a conexão com o banco de dados:

E então arraste a tabela “Foto” para dentro do DataSet tipado:

Após isso, podemos utilizar esse DataSet tipado para salvarmos a imagem no banco. Vamos ver como ficam os métodos “CarregarThumbnailsDataSetTipado“, “SalvarFotoDataSetTipado” e “ExcluirFotoDataSetTipado“:

        private void CarregarThumbnailsDataSetTipado()
        {
            using (FotoDataSetTableAdapters.FotoTableAdapter dataAdapter = new FotoDataSetTableAdapters.FotoTableAdapter())
            {
                FotoDataSet.FotoDataTable dataTable = new FotoDataSet.FotoDataTable();
                dataAdapter.Fill(dataTable);
                fotosDBListBox.DataSource = dataTable;
                fotosDBListBox.DisplayMember = "FotoID";
                fotosDBListBox.ValueMember = "FotoID";
            }
        }

        private void SalvarFotoDataSetTipado()
        {
            using (FotoDataSetTableAdapters.FotoTableAdapter dataAdapter = new FotoDataSetTableAdapters.FotoTableAdapter())
            {
                dataAdapter.Insert(DateTime.Now.ToString(), ConverterFotoParaByteArray());
            }
        }

        private void ExcluirFotoDataSetTipado()
        {
            var dataRowView = fotosDBListBox.SelectedItem as DataRowView;
            if (dataRowView != null)
            {
                using (FotoDataSetTableAdapters.FotoTableAdapter dataAdapter = new FotoDataSetTableAdapters.FotoTableAdapter())
                {
                    dataAdapter.Delete((int)dataRowView.Row["FotoID"], dataRowView.Row["Descricao"].ToString());
                }
            }
        }

Veja que o código utilizando DataSet tipado é muito mais simples que o código utilizando ADO.NET puro. Isso se deve principalmente ao fato da criação do DataAdapter pelo DataSet tipado. Com o DataAdapter fica muito mais fácil adicionar, editar e excluir registros do banco de dados. Basta utilizarmos os métodos específicos para essas ações (Insert, Delete e Fill, como vimos no código acima), sem termos que escrever nenhuma linha de SQL.

É importante ressaltar que a criação de DataAdapters pode também ser feita sem a necessidade de criarmos DataSets tipados. Porém, é muito mais fácil utilizarmos DataSets tipados, uma vez que, nesse caso, os DataAdapters para cada tabela são gerados automaticamente pelo Visual Studio.

Para testar o exemplo, substitua todas as chamadas de “CarregarThumbnailsAdoNet“, “SalvarFotoAdoNet” e “ExcluirFotoAdoNet” por “CarregarThumbnailsDataSetTipado“, “SalvarFotoDataSetTipado” e “ExcluirFotoDataSetTipado” respectivamente.

Salvando a imagem com o Entity Framework

Nessa última seção, vamos verificar como fazer as mesmas ações utilizando o Entity Framework. O primeiro passo que devemos executar é adicionar o contexto para o nosso banco de dados. Para isso, adicione uma pasta no projeto chamada “EntityFramework” e, dentro dessa pasta, adicione um novo item do tipo “ADO.NET Entity Data Model“:

Escolha a opção “EF Designer from database“, escolha a connection string criada anteriormente, marque a tabela “Foto” na lista de objetos do banco de dados e clique em “Finish“:

Durante esse processo, algumas mensagens de segurança serão exibidas. Simplesmente clique “OK” e continue com o processo para gerar o modelo de dados.

Com o contexto em mãos, basta o instanciarmos para termos acesso aos dados da tabela “Foto“. Veja como fica o código para carregar as thumbnails, salvar novas fotos e excluir fotos existentes utilizando o Entity Framework:

        private void CarregarThumbnailsEntityFramework()
        {
            using (EntityFramework.DemoDBEntities context = new EntityFramework.DemoDBEntities())
            {
                fotosDBListBox.DataSource = context.Foto.ToList();
                fotosDBListBox.DisplayMember = "FotoID";
                fotosDBListBox.ValueMember = "FotoID";
            }
        }

        private void SalvarFotoEntityFramework()
        {
            using (EntityFramework.DemoDBEntities context = new EntityFramework.DemoDBEntities())
            {
                context.Foto.Add(new EntityFramework.Foto()
                {
                    Descricao = DateTime.Now.ToString(),
                    Foto1 = ConverterFotoParaByteArray()
                });
                context.SaveChanges();
            }
        }

        private void ExcluirFotoEntityFramework()
        {
            var foto = fotosDBListBox.SelectedItem as EntityFramework.Foto;
            if (foto != null)
            {
                using (EntityFramework.DemoDBEntities context = new EntityFramework.DemoDBEntities())
                {
                    var fotoNoContext = context.Foto.Find(foto.FotoID);
                    context.Foto.Remove(fotoNoContext);
                    context.SaveChanges();
                }
            }
        }

        private void fotosDBListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            var foto = fotosDBListBox.SelectedItem as EntityFramework.Foto;
            if (foto != null)
            {
                using (var stream = new System.IO.MemoryStream(foto.Foto1))
                {
                    thumbnailPictureBox.Image = Bitmap.FromStream(stream);
                }
            }
        }

Observe que é muito simples trabalhar com o Entity Framework. Só temos que criar uma instância do DbContext e utilizar a entidade “Foto” para acessar as fotos cadastradas no banco de dados. Para adicionar uma foto nova, basta criar uma nova instância da classe Foto, adicioná-la à coleção e chamar o método SaveChanges. E para deletar uma foto, basta encontrar o registro na entidade Foto, removê-lo da coleção e chamar o método SaveChanges.

Uma observação importante é que o handler para mostrar o item selecionado na ListBox (“fotosDBListBox_SelectedIndexChanged“) é um pouco diferente de quando estamos utilizando ADO.NET puro ou DataSets tipados. Isso ocorre porque o SelectedItem não será um DataRowView nesse caso, mas sim, uma instância da classe Foto.

Outra observação importante é que o Entity Framework utilizou “Foto1” como nome da coluna “Foto” da nossa tabela. Isso se deve ao fato de que a coluna e a tabela tem nomes iguais, e o Entity Framework não consegue lidar com isso de forma amigável. Nesse caso, o melhor seria ter dado outro nome para a coluna “Foto” (como, por exemplo, “ConteudoFoto“).

Qual dessas opções eu devo utilizar?

Agora que você conhece essas três opções para salvar as imagens no banco de dados, surge a dúvida: qual delas eu devo utilizar? A resposta é aquela clássica: depende. Se você estiver procurando por performance, provavelmente a melhor opção é utilizar ADO.NET puro ou DataSets tipados. Se você estiver procurando por praticidade (e performance não for importante no seu cenário), a melhor opção provavelmente será o Entity Framework.

Não vou abordar esse comparativo, pois o André Baltieri já gravou um vídeo excelente sobre esse tópico. Confira no canal dele no Youtube:

Screencast André Baltieri: ADO puro ou Frameworks ORM?

E com isso eu finalizo o artigo de hoje. Para ficar por dentro das novidades do meu site, assine a minha newsletter clicando aqui ou preenchendo o formulário abaixo. É lá que eu compartilho as notícias dos posts publicados além de enviar informações que eu só divido por e-mail! Por exemplo, o tópico desse post foi baseado em uma sugestão de um inscrito. Não perca tempo e assine agora mesmo!

Até a próxima!

André Lima

Icon by Heart Internet used under Creative Commons
https://www.iconfinder.com/icons/63467/database_storage_icon

Newsletter do André Lima

* indicates required



Powered by MailChimp

12 thoughts on “Salvando imagens no banco de dados utilizando C#

  • […] O tema do artigo de hoje foi inspirado em uma resposta para essa pergunta, vinda de uma pessoa que se inscreveu na semana passada. A sugestão do inscrito era que eu mostrasse como tirar fotos com a webcam em C# e salvá-las em um banco de dados. Como esse é um tema muito grande, vou dividi-lo em duas partes. Nessa primeira parte, vou mostrar como tirar fotos com a webcam em C# e salvá-las no disco (e não no banco de dados). Em um artigo futuro eu vou expandir esse assunto e mostrar como salvar essas fotos em um banco de dados (EDIT: Já escrevi a extensão desse artigo mostrando como salvar as imagens no banco de dados – confira aqui). […]

    • Marcello disse:

      Conferindo aqui… Aí já são 01:28 da manhã aff!!

      Um ótimo dia André! Seguinte. Caí na sua news porque procurava algo para implementar em um sistema de protocolo, o envio da imagem do documento cadastrado junto com os dados no banco SQLServer. Até então só encontrei situações em que primeiro salva-se a imagem no HD e depois procura-se a imagem no HD para manda-la para o banco ou somente salva-la no HD. Estou trabalhando com camadas (Acesso Banco; Objeto Transferência; Negócios e Apresentação). Então fica algumas dúvidas quanto a implementação:
      1 – No caso das referencias em qual bloco devo colocar as dlls e tals.
      2 – Gostaria de salvar os documentos em PDF.

      Caso possa me ajudar ficarei grato.

      Abraços,

      Marcello M. Mariano

      • andrealveslima disse:

        Olá Marcello, obrigado pelo comentário!

        Quanto à sua primeira pergunta, qual referência você quer dizer? A propósito, qual das três maneiras de salvar a imagem no banco você está querendo utilizar?

        Já quanto à sua segunda pergunta, relacionada ao PDF, você pode utilizar a biblioteca PDFSharp para criar o arquivo PDF com o documento:

        http://www.pdfsharp.net/

        Tenho planos de escrever um artigo sobre a geração de PDFs com o C# (acredito que ainda este ano sai), então, fiquei atento aos novos posts.. :)

        Abraço!
        André Lima

  • […] Nesse artigo, aprendemos a coletar as assinaturas e armazená-las em um arquivo no diretório da aplicação. Se você quiser aprender a salvar essas imagens no banco de dados, confira o artigo onde eu mostro como salvar imagens no banco de dados utilizando C#. […]

  • Anderson Silva disse:

    Andre bom dia, promeiramente gostaria de parabenizza-lo pelos ótimos aritogos e aproveito o momento oportuno para lhe fazer uma pergunta que tenho ha meses. Estou construindo uma nova aplicação e vou capturar a imagem pela WebCam , porém minha duvida é onde armazena-la no diretório do windows ou no banco de dados ?. Qual os pros e contras entre essas duas formas ?

    Obrigado.

    • andrealveslima disse:

      Olá Anderson, obrigado pelo comentário!

      Como você disse, as duas opções têm prós e contras..

      Armazenar no diretório do windows tem a vantagem que o seu banco de dados não fica “inchado”, uma vez que as imagens capturadas pela webcam são grandes e o tamanho do seu banco de dados crescerá rapidamente caso você armazene as imagens dentro dele.. A desvantagem é que você não tem controle sobre o sistema de arquivos.. Ou seja, não há nada que impeça alguém de deletar as imagens do sistema de arquivos.. E, caso isso aconteça, o seu sistema perderia a referência a essa imagem e não conseguiria mais exibí-la..

      Já se você armazenar as imagens no banco de dados, as vantagens e desvantagens se invertem.. A vantagem é que você tem total controle das imagens se elas estiverem no banco de dados.. Ninguém conseguirá simplesmente entrar no banco de dados e apagar a imagem (a não ser que ele tenha acesso ao banco de dados e faça isso manualmente, obviamente).. Já a desvantagem é que o tamanho do banco crescerá rapidamente..

      Eu sugiro que, caso você esteja utilizando um banco de dados robusto (SQL Server, MySQL, Postgre, Oracle, etc), armazene as imagens dentro dele.. Porém, se você estiver usando um banco de dados que não seja 100% confiável (como Microsoft Access, SQL CE, etc), talvez seja melhor armazenar no sistema de arquivos (uma vez que esses tipos de bancos de dados se corrompem facilmente, principalmente quando eles crescem muito de tamanho)..

      É isso.. Espero que tenha ajudado..

      Abraço!
      André Lima

  • Lucas disse:

    Olá, André. Explicação excelente! Testei com ADO.Net Puro e deu certo, porém queria testar usando o DataSet tipado, já que é mais prático. O problema é que o banco que estou utilizando é o MySQL, e não consigo adicionar minha tabela ao DataSet. Você sabe onde está o erro?

    Desde já, grato!

    • andrealveslima disse:

      Olá Lucas, obrigado pelo comentário!

      Você só tem que adicionar a conexão no Server Explorer, escolher “Change” na parte do provider e selecionar o provider do MySQL:

      Depois, você entra com as configurações do seu banco e, uma vez conectado, você arrasta as tabelas desejadas para dentro do DataSet..

      Se a opção “MySQL” não estiver aparecendo é porque provavelmente você não instalou todas as ferramentas do MySQL para o .NET.. Se esse for o caso, execute de novo o setup do MySQL e faz a instalação completa (ou pelo menos assegure-se que você marcou a opção “MySQL for Visual Studio”)..

      Abraço!
      André Lima

      • Lucas disse:

        Olá André, obrigado por responder, mas acho que não fui bem específico. Eu já fiz a conexão do MySQL com o Visual Studio (e deu certo, pois já havia feito outros testes com MySQL), porém quando arrasto minha tabela para o DataSet, aparece a seguinte mensagem:

        “Some updating commands could not be generated automatically. The database returned the following error:
        You have a usable connection already”

        Seguido da seguinte mensagem de erro, também:

        “Mouse drag operation failed. Could not retrieve schema information for table or view…”

        Desde já, grato!

        • andrealveslima disse:

          Olá Lucas!

          Muito estranho hein.. Você está utilizando qual versão das ferramentas do MySQL para o Visual Studio? É a mais nova? Encontrei uns links falando sobre esse mesmo problema e era a versão do MySQL for Visual Studio que não era completamente compatível..

          Veja só, aqui no meu computador com Visual Studio 2013 + MySQL for Visual Studio 1.2.3 funciona direitinho:

          Abraço!
          André Lima

          • Lucas disse:

            Obrigado pela ajuda, André. Aproveitando… seria interessante para mim capturar a foto e no mesmo instante ela aparecer em uma segunda pictureBox sem que eu tenha que usar uma listBox para selecionar seu ID… Creio que deve ser algo simples, porém estou com um pouco de dificuldade.

            Grato!

          • andrealveslima disse:

            Olá Lucas!

            Para isso é mais fácil você dar uma olhada no artigo original sobre Webcam com C#.. Você só precisa pegar no evento “Click” do botão e, ao invés de salvar o conteúdo da variável “bitmap” em disco, você configura ele como a Image do segundo PictureBox.. Seria algo como:

            var bitmap = new Bitmap(webCamPictureBox.Width, webCamPictureBox.Height);
            using (var graphics = Graphics.FromImage(bitmap))
            {
                var webCamPoint = webCamPictureBox.PointToScreen(new Point(0, 0));
                graphics.CopyFromScreen(webCamPoint.X, webCamPoint.Y, 0, 0, bitmap.Size);
            }
            suaSegundaPictureBox.Image = bitmap;
            

            Abraço!
            André Lima

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *