使用 Visual C 锐利将图片从数据库直接复制到 PictureBox 控件

本文介绍如何将数据库中存储的图像直接复制到 Windows 窗体上的 PictureBox 控件中,而无需将图像保存到文件中。

原始产品版本: Visual C#
原始 KB 数: 317701

总结

本分步文章介绍如何将数据库中存储的图像直接复制到 Windows 窗体上的 PictureBox 控件中,而无需将图像保存到文件中。

在 Visual Basic 6.0 中,在 PictureBox 控件中显示来自数据库的图像的唯一方法是将二进制大型对象 {BLOB) 数据保存到文件中的中间步骤是将 PictureBox 绑定到 ActiveX 数据对象(ADO)数据控件或记录集等数据源。 无法(没有数据绑定)以编程方式将 BLOB 加载到控件中,而无需将图像保存到文件以供 LoadPicture 语句使用。

在本文中,我们将使用 MemoryStream 基类中的 System.IO 对象将图像数据从数据库直接复制到 PictureBox 控件中。

要求

以下列表概述了所需的推荐硬件、软件、网络基础结构和服务包:

  • 在兼容的 Windows 操作系统上安装的 Visual Studio .NET
  • SQL Server 的可用实例或可用于测试的 Access 数据库

本文假定你熟悉以下主题:

  • Visual C# .NET Windows 窗体应用程序
  • 数据库中的二进制大型对象 (BLOB) 存储
  • ADO.NET 数据访问

示例

  1. 使用以下结构创建 SQL Server 或 Access 表:

    CREATE TABLE BLOBTest
    (
        BLOBID INT IDENTITY NOT NULL,
        BLOBData IMAGE NOT NULL
    )
    
  2. 打开 Visual Studio .NET 并创建新的 Visual C# Windows 应用程序项目。

  3. 从工具箱将 PictureBox 和两个按钮控件添加到默认 Form1。 将Text“文件”的属性Button1设置为“数据库”,并将Text“数据库”的属性Button2设置为 PictureBox

  4. 在窗体代码模块顶部插入以下 using 语句:

    using System.Data.SqlClient;
    using System.IO;
    using System.Drawing.Imaging;
    
  5. 在公共类 Form1 中为数据库添加以下声明连接字符串:System.Windows.Forms.Form class声明并根据需要调整连接字符串:

    String strCn = "Data Source=localhost;integrated security=sspi;initial catalog=mydata";
    
  6. 在事件过程中Button1插入以下代码Click文件到数据库)。 根据需要将文件路径调整为可用的示例图像文件。 此代码将图像文件从磁盘(使用 FileStream 对象)读取到 Byte 数组中,然后使用参数化的 Command 对象将数据插入数据库中。

    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. 在事件过程中Button2插入以下代码Click数据库到 PictureBox)。 此代码从数据库中的 BLOBTest 表中检索行, DataSet将最近添加的图像 Byte 复制到数组中,然后复制到对象 MemoryStream 中,然后加载到 MemoryStream Image 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. F5 编译并运行项目。

  9. 单击“文件到数据库”按钮,将至少一个示例图像加载到数据库中。

  10. 单击“数据库到 PictureBox”按钮,在 PictureBox 控件中显示保存的图像。

  11. 如果希望能够将图片从 PictureBox 控件直接插入到数据库中,请添加第三个 Button 控件并在其 Click 事件过程中插入以下代码。 此代码将 PictureBox 控件中的图像数据检索到对象MemoryStream中,将图像数据复制到MemoryStreamByte数组中,然后使用参数化的 Command 对象将Byte数组保存到数据库。

    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. 运行该项目。 单击“ 数据库到 PictureBox”按钮,在 PictureBox 控件中显示以前保存的图像。 单击新添加的按钮将图片从 PictureBox 保存到数据库中。 然后再次单击“ 数据库到 PictureBox ”按钮,确认图像已正确保存。

陷阱

  • 此测试不适用于使用 Access 和 SQL Server 分发的示例 Northwind 数据库的 Employees 表中的照片列。 存储在“照片”列中的位图图像用 Visual Basic 6.0 OLE 容器控件创建的标头信息进行包装。

  • 如果需要使用 Access 数据库来测试此代码,则需要将 Access 表中的列创建为类型 OLE 对象,并将 System.Data.OleDb 命名空间与 Jet 4.0 提供程序一起使用来代替 System.Data.SqlClient 命名空间。