Copiar una imagen de una base de datos directamente en un control PictureBox con Visual C sharp

En este artículo se describe cómo copiar una imagen almacenada en una base de datos directamente en un control PictureBox en un formulario Windows Form sin necesidad de guardar la imagen en un archivo.

Versión original del producto: Visual C#
Número de KB original: 317701

Resumen

En este artículo paso a paso se describe cómo copiar una imagen almacenada en una base de datos directamente en un control PictureBox en windows Form sin necesidad de guardar la imagen en un archivo.

En Visual Basic 6.0, la única manera de mostrar una imagen de una base de datos en un control PictureBox, sin el paso intermedio de guardar los datos del objeto binario grande {BLOB) en un archivo, es enlazar pictureBox a un origen de datos, como un control de datos ActiveX Data Objects (ADO) o recordset. No hay ninguna manera (sin enlace de datos) de cargar mediante programación un BLOB en un control sin guardar la imagen en un archivo para que la use la instrucción LoadPicture.

En este artículo, usaremos el MemoryStream objeto de la System.IO clase base para copiar los datos de imagen de la base de datos directamente en el control PictureBox.

Requisitos

En la lista siguiente se describen el hardware, el software, la infraestructura de red y los Service Pack recomendados que necesitará:

  • Visual Studio .NET instalado en un sistema operativo Windows compatible
  • Una instancia disponible de SQL Server o una base de datos de Access disponible para pruebas

En este artículo se supone que está familiarizado con los temas siguientes:

  • Aplicaciones de .NET Windows Forms de Visual C#
  • Almacenamiento de objetos binarios grandes (BLOB) en bases de datos
  • acceso a datos de ADO.NET

Muestra

  1. Cree una tabla de SQL Server o Access con la siguiente estructura:

    CREATE TABLE BLOBTest
    (
        BLOBID INT IDENTITY NOT NULL,
        BLOBData IMAGE NOT NULL
    )
    
  2. Abra Visual Studio .NET y cree un nuevo proyecto de aplicación de Windows de Visual C#.

  3. Agregue un PictureBox y dos controles Button al form1 predeterminado desde el cuadro de herramientas. Establezca la Text propiedad de Button1 en Archivo en Base de datos y la Text propiedad de en Base deButton2 datos en PictureBox.

  4. Inserte las instrucciones using siguientes en la parte superior del módulo de código del formulario:

    using System.Data.SqlClient;
    using System.IO;
    using System.Drawing.Imaging;
    
  5. Agregue la siguiente declaración para la base de datos cadena de conexión justo dentro de la clase pública Form1: System.Windows.Forms.Form class declaración y ajuste el cadena de conexión según sea necesario:

    String strCn = "Data Source=localhost;integrated security=sspi;initial catalog=mydata";
    
  6. Inserte el código siguiente en el Click procedimiento de evento de Button1 (Archivo a base de datos). Ajuste la ruta de acceso del archivo a un archivo de imagen de ejemplo disponible según sea necesario. Este código lee el archivo de imagen del disco (mediante un FileStream objeto) en una Byte matriz y, a continuación, inserta los datos en la base de datos mediante un objeto Command con parámetros.

    try
    {
        SqlConnection cn = new SqlConnection(strCn);
        SqlCommand cmd = new SqlCommand("INSERT INTO BLOBTest (BLOBData) VALUES (@BLOBData)", cn);
        String strBLOBFilePath = @"C:\blue hills.jpg";//Modify this path as needed.
    
        //Read jpg into file stream, and from there into Byte array.
        FileStream fsBLOBFile = new FileStream(strBLOBFilePath,FileMode.Open, FileAccess.Read);
        Byte[] bytBLOBData = new Byte[fsBLOBFile.Length];
        fsBLOBFile.Read(bytBLOBData, 0, bytBLOBData.Length);
        fsBLOBFile.Close();
    
        //Create parameter for insert command and add to SqlCommand object.
        SqlParameter prm = new SqlParameter("@BLOBData", SqlDbType.VarBinary, bytBLOBData.Length, ParameterDirection.Input, false,
        0, 0, null, DataRowVersion.Current, bytBLOBData);
        cmd.Parameters.Add(prm);
    
        //Open connection, execute query, and close connection.
        cn.Open();
        cmd.ExecuteNonQuery();
        cn.Close();
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    
  7. Inserte el código siguiente en el Click procedimiento de evento de Button2 (Database to PictureBox). Este código recupera las filas de la BLOBTest tabla de la base de datos en , DataSetcopia la imagen agregada más recientemente en una Byte matriz y, a continuación, en un MemoryStream objeto y, a continuación, carga en MemoryStream la Image propiedad del control PictureBox.

    try
    {
        SqlConnection cn = new SqlConnection(strCn);
        cn.Open();
    
        //Retrieve BLOB from database into DataSet.
        SqlCommand cmd = new SqlCommand("SELECT BLOBID, BLOBData FROM BLOBTest ORDER BY BLOBID", cn);
        SqlDataAdapter da = new SqlDataAdapter(cmd);
        DataSet ds = new DataSet();
        da.Fill(ds, "BLOBTest");
        int c = ds.Tables["BLOBTest"].Rows.Count;
    
        if(c>0)
        {
            //BLOB is read into Byte array, then used to construct MemoryStream,
            //then passed to PictureBox.
            Byte[] byteBLOBData = new Byte[0];
            byteBLOBData = (Byte[])(ds.Tables["BLOBTest"].Rows[c - 1]["BLOBData"]);
            MemoryStream stmBLOBData = new MemoryStream(byteBLOBData);
            pictureBox1.Image= Image.FromStream(stmBLOBData);
        }
        cn.Close();
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    
  8. Presione F5 para compilar y ejecutar el proyecto.

  9. Haga clic en el botón Archivo a base de datos para cargar al menos una imagen de ejemplo en la base de datos.

  10. Haga clic en el botón Database to PictureBox (Base de datos a PictureBox ) para mostrar la imagen guardada en el control PictureBox.

  11. Si desea poder insertar la imagen desde el control PictureBox directamente en la base de datos, agregue un tercer control Button e inserte el código siguiente en su Click procedimiento de evento. Este código recupera los datos de imagen del control PictureBox en un MemoryStream objeto, copia en MemoryStream una Byte matriz y, a continuación, guarda la Byte matriz en la base de datos mediante un objeto Command parametrizado.

    try
    {
        SqlConnection cn = new SqlConnection(strCn);
        SqlCommand cmd = new SqlCommand("INSERT INTO BLOBTest (BLOBData) VALUES (@BLOBData)", cn);
    
        //Save image from PictureBox into MemoryStream object.
        MemoryStream ms = new MemoryStream();
        pictureBox1.Image.Save(ms, ImageFormat.Jpeg);
    
        //Read from MemoryStream into Byte array.
        Byte[] bytBLOBData = new Byte[ms.Length];
        ms.Position = 0;
        ms.Read(bytBLOBData, 0, Convert.ToInt32(ms.Length));
    
        //Create parameter for insert statement that contains image.
        SqlParameter prm = new SqlParameter("@BLOBData", SqlDbType.VarBinary, bytBLOBData.Length, ParameterDirection.Input, false,
        0, 0,null, DataRowVersion.Current, bytBLOBData);
        cmd.Parameters.Add(prm);
        cn.Open();
        cmd.ExecuteNonQuery();
        cn.Close();
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    
  12. Ejecute el proyecto. Haga clic en el botón Base de datos a PictureBox para mostrar una imagen guardada anteriormente en el control PictureBox. Haga clic en el botón recién agregado para guardar la imagen de PictureBox en la base de datos. A continuación, haga clic en el botón De base de datos a PictureBox de nuevo para confirmar que la imagen se guardó correctamente.

Trampas

  • Esta prueba no funcionará con la columna Photo de la tabla Employees de la base de datos northwind de ejemplo distribuida con Access y SQL Server. Las imágenes de mapa de bits almacenadas en la columna Photo se ajustan con la información de encabezado creada por el control contenedor OLE de Visual Basic 6.0.

  • Si necesita usar una base de datos de Access para probar este código, deberá crear la columna en la tabla de Access como tipo objeto OLE y usar el System.Data.OleDb espacio de nombres con el proveedor de Jet 4.0 en lugar del System.Data.SqlClient espacio de nombres.