为啥二进制中的 Sql Server 图像在字符串查询中导致问题但在参数化查询中有效
Posted
技术标签:
【中文标题】为啥二进制中的 Sql Server 图像在字符串查询中导致问题但在参数化查询中有效【英文标题】:Why Sql Server Image In Binary Causes Issue in string Query but works in Parameterized Query为什么二进制中的 Sql Server 图像在字符串查询中导致问题但在参数化查询中有效 【发布时间】:2014-04-25 12:48:57 【问题描述】:我将图像保存在VarBinary
的表中及其工作。但问题是,如果我在 检索 时使用字符串查询保存图像,它会说参数无效,尽管图像二进制文件已保存在数据库中,我可以看到它。但如果我使用 parametrized 查询和 retrieve 图像,它会正确显示:
这是我的参数化查询代码:
try
byte[] byteImg = ImageToByteArray(pictureBox1.Image);
connection = con.getConnection();
if (connection != null)
query = @"INSERT INTO [tblImages]
([Image])
VALUES
(@image)";
connection.Open();
cmd = new SqlCommand(query, connection);
cmd.Parameters.AddWithValue("@image", byteImg);
cmd.ExecuteNonQuery();
MessageBox.Show("Saved");
connection.Close();
pictureBox1.Image = null;
catch (Exception ex)
MessageBox.Show(ex.Message);
使用参数化的数据库行视图:
这是我的字符串查询代码:
try
byte[] byteImg = ImageToByteArray(pictureBox1.Image);
connection = con.getConnection();
if (connection != null)
query = @"INSERT INTO [tblImages]
([Image])
VALUES
(Convert(varbinary(MAX),'" + byteImg + "'))";
connection.Open();
cmd = new SqlCommand(query, connection);
cmd.ExecuteNonQuery();
MessageBox.Show("Saved");
connection.Close();
pictureBox1.Image = null;
catch
字节转换方法:
public byte[] ImageToByteArray(Image img)
System.IO.MemoryStream ms = new System.IO.MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
return ms.ToArray();
数据库行视图:
为什么会发生这种情况,为什么使用参数化查询二进制在行中不同,而使用字符串查询不同,这很奇怪。
任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:你实际上可以这样做:
INSERT INTO [tblImages] ([Image])
VALUES 0x5379......
要构建二进制字符串,请使用这样的代码(缓冲区是您的字节数组)
_sbScript.Append("0x");
for (int i = 0; i < buffer.Length; i++)
_sbScript.Append(buffer[i].ToString("X2",System.Globalization.CultureInfo.InvariantCulture));
【讨论】:
十六进制格式:msdn.microsoft.com/en-us/library/…【参考方案2】:在第二个数据快照 (0x53797374...
) 的十六进制中,所有字节都拼出了类型名称(也许是“System.Byte[]”?我停止翻译...)。
0x53 - 'S'
0x79 - 'y'
0x73 - 's'
0x74 - 't'
0x65 - 'e'
0x6D - 'm'
当您使用 CONVERT(VARBINARY(MAX), '" + array + "')"
构建字符串时,将调用数组 ToString 方法,该方法在 System.Array 上没有很好地定义并返回类型的名称。然后你的 Sql 看起来像 INSERT INTO ... (CONVERT(VARBINARY(MAX), 'System.Byte[]')
并且会错误地插入到数据库中。
选择参数化选项肯定是更安全的方法(就安全性和潜在错误而言),但如果您想将其作为 SQL 字符串执行,您将需要构建一个实际字节的字符串,如 ErikEJ 的回答所示。
【讨论】:
【参考方案3】:您在字符串查询代码中有不同的 INSERT 语句。
参数化查询代码为:
query = @"INSERT INTO [tblImages]
([Image])
VALUES (@image)";
而字符串查询代码为:
query = @"INSERT INTO [tblImages]
([Image])
VALUES (Convert(varbinary(MAX),'" + byteImg + "'))";
删除CONVERT
应该会使两个语句以相同的方式插入。
【讨论】:
以上是关于为啥二进制中的 Sql Server 图像在字符串查询中导致问题但在参数化查询中有效的主要内容,如果未能解决你的问题,请参考以下文章