【问题标题】:How to update database records even if the image is not changed即使图像未更改,如何更新数据库记录
【发布时间】:2021-03-11 09:46:08
【问题描述】:

我使用 localDB 作为我的数据库。

我有一张员工表,员工图片存储在另一个表中

这是我用于创建和更新的存储过程:

    IF NOT EXISTS (SELECT * 
                   FROM   dbo.Employee 
                   WHERE  employee_id=@employee_id)   
    BEGIN TRY
        BEGIN TRAN
            INSERT INTO dbo.Employee 
            (employee_name,
             city,
             department,
             gender
            )  
            OUTPUT inserted.employee_id 
            INTO   @employee_id_PK (employee_id) 
            VALUES 
            (@employee_name,
             @city,
             @department,
             @gender
            )  
            
            SELECT @FK_Employee_Image_To_Employee_Table = employee_id 
            FROM   @employee_id_PK 
            INSERT INTO dbo.Employee_Image
            (user_image,
             file_extension,
             employee_id
            )
            VALUES
            (@user_image,
             @file_extension,
             @FK_Employee_Image_To_Employee_Table
            )
        COMMIT TRAN 
    END TRY

    BEGIN CATCH
        IF @@TRANCOUNT > 0
            ROLLBACK TRAN --RollBack in case of Error
        RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
    END CATCH
            

    ELSE  
    BEGIN TRY
        BEGIN TRAN
            UPDATE e
            SET    e.employee_name=@employee_name,
                  e.city=@city,
                  e.department=@department,  
                  e.gender=@gender
            FROM   dbo.Employee e, dbo.Employee_Health_Insurance h
            WHERE  e.employee_id=@employee_id AND h.employee_id=@employee_id
                                                                         
            UPDATE i
            SET    i.user_image=@user_image,
                  i.file_extension=@file_extension
            FROM   dbo.Employee_Image i, dbo.Employee e
            WHERE  i.employee_id=@employee_id AND e.employee_id=@employee_id
        COMMIT TRAN
    END TRY

    BEGIN CATCH
        IF @@TRANCOUNT > 0
            ROLLBACK TRAN --RollBack in case of Error
        RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
    END CATCH 


这就是我通过 C# 添加记录的方式

using (SqlConnection con = new SqlConnection(connectionStringConfig))
using (SqlCommand sqlCmd = new SqlCommand("spCreateOrUpdateData", con))
{
try
{
    con.Open();
    sqlCmd.CommandType = CommandType.StoredProcedure;

    //Employee Record
    sqlCmd.Parameters.Add("@employee_id", SqlDbType.NVarChar).Value = EmployeeId;
    sqlCmd.Parameters.Add("@employee_name", SqlDbType.NVarChar, 250).Value = txtEmpName.Text;
    sqlCmd.Parameters.Add("@city", SqlDbType.NVarChar, 50).Value = txtEmpCity.Text;
    sqlCmd.Parameters.Add("@department", SqlDbType.NVarChar, 50).Value = txtEmpDept.Text;
    sqlCmd.Parameters.Add("@gender", SqlDbType.NVarChar, 6).Value = cboEmpGender.Text;

    //Employee Image 
    sqlCmd.Parameters.Add("@user_image", SqlDbType.VarBinary, 8000).Value = ConvertImageToByteArray(pictureBox1.Image); <-----------------error here according to StackTrace
    sqlCmd.Parameters.Add("@file_extension", SqlDbType.VarChar, 12).Value = lblFileExtension.Text;

    int numRes = sqlCmd.ExecuteNonQuery();
    string ActionType = (btnSave.Text == "Save") ? "Saved" : "Updated";
    if (numRes > 0)
    {
        MessageBox.Show($"{ txtEmpName.Text }'s record is { ActionType } successfully !!!");
        RefreshData();
    }
    else
        MessageBox.Show($"{txtEmpName.Text} Already Exist !!!");
}
catch (Exception ex)
{
    MessageBox.Show($"Cannot INSERT or UPDATE data! \nError: { ex.Message }");
}

这就是我将图像转换为 byte[] 数组的方式:

byte[] ConvertImageToByteArray(Image img)
{
    //with memory stream:
    /*[1]
    using (MemoryStream ms = new MemoryStream())
    {
        img.Save(ms, img.RawFormat);<-----------------error here according to StackTrace
        return ms.ToArray();
    }*/

    /*[2]
    using (MemoryStream ms = new MemoryStream())
    {
        img.Save(ms, img.RawFormat);<-----------------error here according to StackTrace
        byte[] arrImage = ms.GetBuffer();
        return arrImage;
    }*/


    // with image converter
    /*ImageConverter converter = new ImageConverter();
    return (byte[])converter.ConvertTo(img, typeof(byte[]));*/ <-------------error here according to StackTrace
}

我在将图像转换为字节数组时尝试了上面的代码,当我将它INSERT到数据库时它是成功的,但是当我UPDATE一条记录时(例如更改了"Employee's name") 不更改图像将显示错误:“GDI+ 发生一般错误。”

编辑:

它与检索图像有关吗?

我没有在我的 datagridview 上显示我的图像二进制数据,但我像这样显示/检索我的图像:

private void dgvEmpDetails_CellClick(object sender, DataGridViewCellEventArgs e)
{
    try
    {
        if (e.RowIndex != -1)
        {
            DataGridViewRow row = dgvEmpDetails.Rows[e.RowIndex];
            EmployeeId = row.Cells[0].Value?.ToString();             
            txtEmpName.Text = row.Cells[1].Value?.ToString();
            txtEmpCity.Text = row.Cells[2].Value?.ToString();
            txtEmpDept.Text = row.Cells[3].Value?.ToString();
            cboEmpGender.Text = row.Cells[4].Value?.ToString();

            //Display user image
            using (SqlConnection con = new SqlConnection(connectionStringConfig))
            using (SqlCommand sqlCmd = new SqlCommand("SELECT user_image, file_extension FROM dbo.Employee_Image WHERE employee_id=@employee_id", con))
            {
                con.Open();
                sqlCmd.Parameters.Add("@employee_id", SqlDbType.NVarChar).Value = EmployeeId;

                using (SqlDataReader reader = sqlCmd.ExecuteReader())
                {
                    if (reader.HasRows)
                    {
                        reader.Read();
                        pictureBox1.Image = ConvertByteArrayToImage((byte[])(reader.GetValue(0))); <------------- displaying the image here
                        lblFileExtension.Text = reader.GetValue(1).ToString();
                    }
                    else
                    {
                        pictureBox1.Image = null;
                    }
                }
            }
            btnSave.Text = "Update";
            btnDelete.Enabled = true;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Something is wrong with the selected record! \nError: { ex.GetType().FullName }");
    }
}

我将字节数组转换为图像的方法:

public static Image ConvertByteArrayToImage(byte[] byteArrayIn)
{
    using (MemoryStream ms = new MemoryStream(byteArrayIn))
    {
        Image returnImage = Image.FromStream(ms);
        return returnImage;
    }
}

【问题讨论】:

  • 对于通用 GDI+ 错误,通常与处理创建图像对象的流有关。
  • 旁注:不要在连接打开时用长计算或消息框阻塞线程。由于只插入一条记录,所以不需要OUTPUT,可以使用SCOPEIDENTITY()获取最新的标识值
  • @Llama 但我在 ConvertImageToByteArray() 方法中使用了 using 语句。还是我做错了?
  • 嘿@Charlieface你能详细说明什么是“线程”吗?我在一些stackoverflow问题和答案中看到了它,但我仍然没有很好地掌握它。而且,我还发现(在堆栈溢出中)使用输出要好得多。
  • 我认为this question 可能会有所帮助。

标签: c# winforms picturebox localdb


【解决方案1】:

我已经通过修改这个方法解决了这个问题:https://stackoverflow.com/a/14866755/11565087

这是我将图片从图片框转换为字节[]的代码:

public static byte[] ImageToBytes(Image userImage)//Get bytes of the image
{
    using (MemoryStream ms = new MemoryStream())
    using (Bitmap tempImage = new Bitmap(userImage))
    {
        /*copy the object (userImage) into a new object (tempImage), 
            then use that object(tempImage) to "Write" */
        tempImage.Save(ms, userImage.RawFormat);
        return ms.ToArray();
    }
}

这是我从数据库中转换图像的二进制数据并将其加载到我的图片框的代码:

public static Image BytesToImage(byte[] buffer) //Get image from database
{
    using (MemoryStream ms = new MemoryStream(buffer))
    {
        return Image.FromStream(ms);
    }
}

【讨论】:

    【解决方案2】:

    这是我从数据库中获取图像的方法

       // This method use to update the form.
        private void loadFormWithID(int ID)
        {
            dbServer conn = new dbServer(sysController.getConn);
            DataTable tbl = conn.getQueryList("SELECT * FROM Products WHERE ID = " + ID);
            DataRow row = tbl.Rows[0];      
            // This is how i update the Picture Box
            pictureBoxItem.Image = row["Image"] == DBNull.Value ? pictureBoxItem.InitialImage : ImageController.bytesToImage((byte[])row["Image"]);  
         }
    

    这是我与数据库通信的 dbserver 类。

       public class dbServer
       {
            public string _connectionLink;
    
            public dbServer(string connectionString)
            {
                _connectionLink = connectionString; 
            }
    
            public DataTable getQueryList(string sqlQuery)
            {
                 DataTable tbl = new DataTable();
    
               using (SqlConnection conn = new SqlConnection(_connectionLink))
               {
                   using (SqlCommand cmd = new SqlCommand(sqlQuery, conn))
                    {
                       conn.Open();
                       SqlDataReader reader = cmd.ExecuteReader();
                       tbl.Load(reader);
                    }
                }
                return tbl;
            }
       }
    

    我希望这能解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-31
      • 1970-01-01
      • 1970-01-01
      • 2016-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多