即使图像未更改,如何更新数据库记录
How to update database records even if the image is not changed
我正在使用 localDB 作为我的数据库。
我有一个员工table,员工图片存储在另一个table
这是我创建和更新的存储过程:
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 记录(例如更改“员工姓名”)而不更改图像将显示错误:“GDI+ 发生一般错误。”
编辑:
是否与检索图像有关?
我没有在我的 datagridview 上显示我的图像二进制数据,但我 display/retreive 我的图像是这样的:
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;
}
}
我已经通过修改这个方法解决了这个问题:
这是我将图片从 pictureBox 转换为字节的代码[]:
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();
}
}
这是我的代码,用于从数据库转换图像的二进制数据并将其加载到我的 pictureBox:
public static Image BytesToImage(byte[] buffer) //Get image from database
{
using (MemoryStream ms = new MemoryStream(buffer))
{
return Image.FromStream(ms);
}
}
这是我从数据库中获取图像的方法
// 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"]);
}
这是我的数据库服务器 class,它与数据库通信。
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;
}
}
我希望这能解决问题。
我正在使用 localDB 作为我的数据库。
我有一个员工table,员工图片存储在另一个table
这是我创建和更新的存储过程:
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 记录(例如更改“员工姓名”)而不更改图像将显示错误:“GDI+ 发生一般错误。”
编辑:
是否与检索图像有关?
我没有在我的 datagridview 上显示我的图像二进制数据,但我 display/retreive 我的图像是这样的:
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;
}
}
我已经通过修改这个方法解决了这个问题:
这是我将图片从 pictureBox 转换为字节的代码[]:
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();
}
}
这是我的代码,用于从数据库转换图像的二进制数据并将其加载到我的 pictureBox:
public static Image BytesToImage(byte[] buffer) //Get image from database
{
using (MemoryStream ms = new MemoryStream(buffer))
{
return Image.FromStream(ms);
}
}
这是我从数据库中获取图像的方法
// 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"]);
}
这是我的数据库服务器 class,它与数据库通信。
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;
}
}
我希望这能解决问题。