469,282 Members | 1,734 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,282 developers. It's quick & easy.

Insert Byte array to SQL Server using string

Hi,
I am trying to insert a record into a database table, one field of which is
a byte array.

Using the below:

Byte[] imgArr;

.... <code to put image into imgArr>

String sbSQL = "INSERT INTO qlink (qlink_name, qlink_start, qlink_end,
qlink_image, qlink_allday, "
+ "qlink_am, qlink_pm, qlink_default_text, qlink_default_notes) VALUES ('"
+ ButtonCaption + "', '" + DefaultStartTime + "', '" + DefaultEndTime + "',"
+ imgArr + ", " + Convert.ToInt16(AllDay) + ", " + Convert.ToInt16(AMOnly)
+ ", " + Convert.ToInt16(PMOnly) + ", '" + DefaultDescription.Replace("'",
"''")
+ "', '" + DefaultNotes.Replace("'", "''") + "');";

SqlCommand sbCMD = new SqlCommand(sbSQL, dbConn);
try
{
sbCMD.ExecuteScalar();
}

But it fails when the query executes, because in my SQL, imgArr has been
replaced by "System.Byte[]" (i.e. what the "ToString()" method would do)
rather than the array of bytes...
So, I understand why it's doing it, but how do I get around it? Googling
I've seen mention of using command builders and datasets or datatables and
parameters and so on, but it seems like a load more work!

James.

Nov 1 '06 #1
7 32587
You should probably look at parameterised queries; also, I suspect
ExecuteNonQuery may work better.

Can I copy a reply from a while back, which discussed efficient insertion of
image (byte[]) data into SqlServer (in this case from a stream)? This is
intended for illustration only; obviously streams are different to arrays;
you *may* be able to get away with simply throwing the entire byte[] at the
server in one go... maybe...

/* Corresponding SP:

ALTER PROC mgtsave @id int, @data image, @append bit = 1
AS
DECLARE @ptr binary(16)
IF @append = 0 -- need to put in some empty data (not null) for
TEXTPTR to work
UPDATE MGT
SET data = ''
WHERE id = @id

SELECT @ptr = TEXTPTR(data)
FROM MGT
WHERE id = @id

IF @append = 1
UPDATETEXT MGT.data @ptr NULL 0 @data
ELSE
WRITETEXT MGT.data @ptr @data

*/
static void Main() {
long totalBytes = 0;
using (FileStream input = File.OpenRead(@"C:\Out.pdf")) //
random file
using (SqlConnection conn = new
SqlConnection(Properties.Settings.Default.ConKey))
using (SqlCommand cmd = conn.CreateCommand()) {
cmd.Parameters.Add("@id", System.Data.SqlDbType.Int).Value =
1; // just a row marker
SqlParameter paramData = cmd.Parameters.Add("@data",
System.Data.SqlDbType.Image); // the binary
SqlParameter paramAppend = cmd.Parameters.Add("@append",
System.Data.SqlDbType.Bit); // replace or append?
paramAppend.Value = false; // first pass should replace
existing
cmd.CommandText = "mgtsave";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Prepare();
const int SQL_IMAGE_BUFFER_SIZE = 8040; // optimal chunk
size
byte[] buffer = new byte[SQL_IMAGE_BUFFER_SIZE];
int bytesRead;
conn.Open();
while((bytesRead = input.Read(buffer, 0,
SQL_IMAGE_BUFFER_SIZE)) 0) {
if(bytesRead==SQL_IMAGE_BUFFER_SIZE) { // pass the
filled buffer
paramData.Value = buffer;
} else { // didn't fill an entire buffer
byte[] smallBuffer = new byte[bytesRead];
Buffer.BlockCopy(buffer, 0, smallBuffer, 0,
bytesRead);
paramData.Value = smallBuffer;
}
cmd.ExecuteNonQuery();
paramAppend.Value = true; // subsequent calls should
append data
totalBytes += bytesRead;
}
conn.Close();
input.Close();
}
Console.WriteLine(totalBytes);
Console.ReadLine();

}

Nov 1 '06 #2
Hi,
....
So, I understand why it's doing it, but how do I get around it? Googling I've
seen mention of using command builders and datasets or datatables and
parameters and so on, but it seems like a load more work!

James.
As you are searching the web, search also for "sql command injection
attack" for some reasons why it's not such a good idea to build your
own sql-command-strings this way. This attack will not work if you use
parameters.

Hans Kesting
Nov 1 '06 #3

"Hans Kesting" <ne***********@spamgourmet.comwrote in message
news:mn***********************@spamgourmet.com...
>Hi,
...
>So, I understand why it's doing it, but how do I get around it? Googling
I've seen mention of using command builders and datasets or datatables
and parameters and so on, but it seems like a load more work!

James.

As you are searching the web, search also for "sql command injection
attack" for some reasons why it's not such a good idea to build your own
sql-command-strings this way. This attack will not work if you use
parameters.

Hans Kesting
I'm already a bit aware of that from some php stuff I did a while back. This
particular issue is a Winforms app rather than a web one, so hopefully it
shouldn't be such a problem, although Marc's post points towards using
stored procedures and params as well, so it's probably the way to go.
James.

Nov 1 '06 #4
winforms doesn't protect against this, *except* that winforms are generally
intranet based, so you have a *slightly* less hostile client. But it still
doesn't stop people putting in surnames as "o'neil", or more hostile
injection attacks.

The "sp" vs "parameterised text query" debate is one that will run and run.
And run. Personally I like SPs as they give me more granular security and
object promotion processes. Other people like parameterised SQL built via
(for instance) C#. I don't personally get that excited about this dilemma!
Horses for courses.

But yup; don't go near string concatenation unless you *really* know what
you are doing and what every allowed input is (and enforce this...). This
can be useful e.g. when the column name is selected at runtime, so can't be
done as a SQL parameter (sp or otherwise).

Marc
Nov 1 '06 #5
Hi James,

What you would want to do, if you decide to stick with a textual query, is to
convert the Byte[] into a string of byte values that are formatted in
Hexidecimal:

string imgStr = "0x" + BitConverter.ToString(imgArr).Replace("-",
string.Empty);

The imgStr value should not be quoted when inserted into the textual query
(like you would do for a varchar, for instance).

Note: If you have large images or just a large number of them there are more
efficient ways to get a hex string from the Byte[] - just search for "dotnet
Byte[] format Hex" in google groups and you'll find some posts. For example,
I've seen people use a hex-lookup table in memory.

I agree with Marc, however, that you may want to think about using
parameterized queries or stored procedures if only because you may forget to
escape the ' character from time to time, but it will probably help
performance as well, make your code more legible and probably make debugging
easier.

--
Dave Sexton

"james" <ja***@com.comwrote in message
news:45**********************@news.zen.co.uk...
Hi,
I am trying to insert a record into a database table, one field of which is
a byte array.

Using the below:

Byte[] imgArr;

... <code to put image into imgArr>

String sbSQL = "INSERT INTO qlink (qlink_name, qlink_start, qlink_end,
qlink_image, qlink_allday, "
+ "qlink_am, qlink_pm, qlink_default_text, qlink_default_notes) VALUES ('"
+ ButtonCaption + "', '" + DefaultStartTime + "', '" + DefaultEndTime + "',"
+ imgArr + ", " + Convert.ToInt16(AllDay) + ", " + Convert.ToInt16(AMOnly)
+ ", " + Convert.ToInt16(PMOnly) + ", '" + DefaultDescription.Replace("'",
"''")
+ "', '" + DefaultNotes.Replace("'", "''") + "');";

SqlCommand sbCMD = new SqlCommand(sbSQL, dbConn);
try
{
sbCMD.ExecuteScalar();
}

But it fails when the query executes, because in my SQL, imgArr has been
replaced by "System.Byte[]" (i.e. what the "ToString()" method would do)
rather than the array of bytes...
So, I understand why it's doing it, but how do I get around it? Googling
I've seen mention of using command builders and datasets or datatables and
parameters and so on, but it seems like a load more work!

James.

Nov 1 '06 #6

"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:eH**************@TK2MSFTNGP02.phx.gbl...
Hi James,

What you would want to do, if you decide to stick with a textual query, is
to convert the Byte[] into a string of byte values that are formatted in
Hexidecimal:

string imgStr = "0x" + BitConverter.ToString(imgArr).Replace("-",
string.Empty);

The imgStr value should not be quoted when inserted into the textual query
(like you would do for a varchar, for instance).

Note: If you have large images or just a large number of them there are
more efficient ways to get a hex string from the Byte[] - just search for
"dotnet Byte[] format Hex" in google groups and you'll find some posts.
For example, I've seen people use a hex-lookup table in memory.

I agree with Marc, however, that you may want to think about using
parameterized queries or stored procedures if only because you may forget
to escape the ' character from time to time, but it will probably help
performance as well, make your code more legible and probably make
debugging easier.
Thanks for that Dave - I already changed the code to use parameters
yesterday and it seems to insert fine - nice to know there was a way to do
it in the "original" fashion too though. At the moment, I am storing a few
32x32 images, so it's not massive amounts of data (it's basically storing an
icon to be displayed on a button, these are configurable by the user, and
stored in the DB to eliminate file path problems etc...)

James.

Nov 2 '06 #7
Thanks it worked out!
james wrote:
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:eH**************@TK2MSFTNGP02.phx.gbl...
Hi James,

What you would want to do, if you decide to stick with a textual query, is
to convert the Byte[] into a string of byte values that are formatted in
Hexidecimal:

string imgStr = "0x" + BitConverter.ToString(imgArr).Replace("-",
string.Empty);

The imgStr value should not be quoted when inserted into the textual query
(like you would do for a varchar, for instance).

Note: If you have large images or just a large number of them there are
more efficient ways to get a hex string from the Byte[] - just search for
"dotnet Byte[] format Hex" in google groups and you'll find some posts.
For example, I've seen people use a hex-lookup table in memory.

I agree with Marc, however, that you may want to think about using
parameterized queries or stored procedures if only because you may forget
to escape the ' character from time to time, but it will probably help
performance as well, make your code more legible and probably make
debugging easier.

Thanks for that Dave - I already changed the code to use parameters
yesterday and it seems to insert fine - nice to know there was a way to do
it in the "original" fashion too though. At the moment, I am storing a few
32x32 images, so it's not massive amounts of data (it's basically storing an
icon to be displayed on a button, these are configurable by the user, and
stored in the DB to eliminate file path problems etc...)

James.
Dec 14 '06 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by Jarrod Sharp | last post: by
1 post views Thread by ZorpiedoMan | last post: by
2 posts views Thread by Jaime Stuardo | last post: by
10 posts views Thread by Danny | last post: by
reply views Thread by suresh191 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.