Hi,
Having a bit of trouble with the Parameter.AppendChunk method. The
test output from the below code is as follows:
Trace: param first byte: 0
Trace: param second byte: 255
Trace: Source first byte: 255
Trace: Original file length: 711
Trace: total bytes appended to param: 711
Trace: final param length: 712
Trace: param last byte: 217
Trace: Source last byte: 217
For some reason it appears that the first time I'm call the method,
it's putting a 0 in the first byte of the Parameter value. It's my
understanding that the first time the method is called it's supposed
to replace the current contents of the value, and when I've done these
tests against field objects using that that object's version of the
same method it works fine.
In this case however, after I've stored the data to the parameter's
value field it is always 1 byte longer than the original data and when
I call Command.Execute, that same data with the extra 0 byte is stored
to the data source.
Unless I've done something specifically wrong here, it appears that
this might be an ADO bug because I've tried it against two different
data source providers and have the same results.
Thanks
Eric
' get a reference an empty byte array
' to read byte arrays from test file
binArr = TestFunctions.GetByteArr()
Set param1 = command1.CreateParameter( _
"@binValue", adLongVarBinary, _
adParamInput,_
fileSize+1, binArr)
Set param2 = command1.CreateParameter( _
"@Key", adInteger, _
adParamInput, 0, 0)
command1.Parameters.Append param1
command1.Parameters.Append param2
command1.Parameters("@Key") = 1
For each col_name in testArr
strSQL = "UPDATE ado_test SET " & _
col_name & " = ? WHERE " & key_column & " = ?"
command1.CommandText = strSQL
blockSize = 100
While bytesTotalWritten <> fileSize
If fileSize - bytesTotalWritten < blockSize Then
blockSize = fileSize - bytesTotalWritten
End If
' Reads binary file on block at a time
iReturn = TestFunctions.GetBytesFromFile( _
binArr, bytesTotalWritten, _
blockSize, FILE )
' write the bytes to the field
command1.Parameters("@binValue").AppendChunk (binArr)
'DEBUG
If bFirst Then
Assert.Trace "param first char: " & Int(ascB(MidB
(command1.Parameters("@binValue"), 1,1)))
Assert.Trace "param second char: " & Int(ascB(MidB
(command1.Parameters("@binValue"), 2,1)))
Assert.Trace "Source first char: " & Int(ascB(MidB (binArr,1,1)))
End If
bytesTotalWritten = bytesTotalWritten + blockSize
bFirst = cBool(false)
Wend
' DEBUG
Assert.Trace "Original file length: " & fileSize
Assert.Trace "total bytes appended to param: " & bytesTotalWritten
Assert.Trace "final param length: " &
lenB(command1.Parameters("@binValue"))
Assert.Trace "param last char: " & Int(ascB(MidB
(command1.Parameters("@binValue"), 712,1)))
Assert.Trace "Source last char: " & Int(ascB(MidB (binArr,11,1)))
command1.execute
Next
everymn@yahoo.com - 21 Jun 2007 03:14 GMT
I should add that when creating the first parameter to store the
binary data, I was forced to declare the size so..
Set param1 = command1.CreateParameter( _
"@binValue", adLongVarBinary,_
adParamInput, fileSize+1, binArr)
If I stated the size of the field as fileSize which is the exact size
of the date, I get this error when I perform command.Execute
Probably this is because the extra 0 as the first byte is causing an
overflow if I don't create the param with an extra byte in it
Error: Source: ADODB.Command Line 202 Column 2
Application uses a value of the wrong type for the current operation.
everymn@yahoo.com - 22 Jun 2007 05:09 GMT
I've determined where the extra byte is coming from but I'm not sure
what to do about it. I'm doing this in VBs, and since byte() are not
supported there I'm calling a DLL I made in VB6 to create and modify
them for me. When I do this...
>' get a reference an empty byte array
>' to read byte arrays from test file
>binArr = TestFunctions.GetByteArr()
I'm calling...
Public Function GetByteArr() As Byte()
Dim arr(0) As Byte
GetByteArr = arr
End Function
If I change the dimension to arr(10), then the length of my final
parameter value goes up by 10. What I'm unlear about is that
supposedly the first time you call appendChunk, it's supposed to
initialize the variable. I've tried to dimension it as arr() as Byte,
but then when I do this it tells me I'm trying to use the wrong data
type.
>Set param1 = command1.CreateParameter( _
> "@binValue", adLongVarBinary, _
> adParamInput,_
> fileSize+1, binArr)
Is there a more appropriate way to initialize the array that I haven't
tried?
Thanks
Eric
Mark J. McGinty - 25 Jun 2007 11:37 GMT
> I've determined where the extra byte is coming from but I'm not sure
> what to do about it. I'm doing this in VBs, and since byte() are not
[quoted text clipped - 26 lines]
> Is there a more appropriate way to initialize the array that I haven't
> tried?
Have you tried omitting the value arg when you create the parameter object?
Perhaps CreateParameter internally calls AppendChunk if/when a value is
explicitly passed?
Also, there is another way to transfer blob values that works with recordset
fields, so should work with Parameter values as well:
Dim s As ADODB.Stream
Set s = New ADODB.Stream
s.Mode = adModeReadWrite
s.Type = adTypeBinary
s.Open
' load binary contents of into stream
' assumes FileName is the name of an existing file
s.LoadFromFile FileName
' set position to beginning of stream
s.Position = 0
' insert a row (or otherwise position record pointer)
rs.AddNew
' assign other fields as required
' ...
' assumes image field name is 'blob'
rs.Fields("blob").value = s.Read()
rs.Update
s.Close
-Mark
> Thanks
> Eric
everymn@yahoo.com - 25 Jun 2007 19:42 GMT
Mark,
Yes, good call, that's exactly what it was doing.
Thanks
Just out of curiousity, is there a direct way to read data a block at
a time from a Stream? Here I've been using the Get method as follows
Open FilePath For Binary Access Read As #fileIndex
Get #fileIndex, offset, arrBin2
Close
Thanks
Eric
>Have you tried omitting the value arg when you create the parameter object?
>Perhaps CreateParameter internally calls AppendChunk if/when a value is
[quoted text clipped - 29 lines]
>> Thanks
>> Eric
Mark J. McGinty - 30 Jun 2007 08:49 GMT
> Mark,
>
[quoted text clipped - 6 lines]
> Get #fileIndex, offset, arrBin2
> Close
The Stream's Read method accepts an optional NumBytes parameter, but I'm not
sure how it could be used to chunk-up a blob parameter -- I take it you're
working with large files and need to show progress? If that's the case, the
stream may not offer you any advantages.
As I was drafting this, and experimenting a little in an unsaved project, I
noticed that Open accepts adOpenStreamAsync as an option, but apparently
that only applies to certain types of sources. I also saw that loading a
multi-hundred MB file into a stream blocks for longer than most users like
to see a frozen UI...
But my experiment ended when I was left once again to lament that VB6's
debugger somehow parents the debug target, such that msgbox blocks access to
the debugger IDE -- gah what a horrible design flaw! You'd think they'd
have provided some way to kill the debug target without killing the IDE, no
matter what the target was doing, ala VS[every version I've used] C++ apps,
but oh no...
Anyway, good luck with your project.
-Mark
> Thanks
> Eric
[quoted text clipped - 34 lines]
>>> Thanks
>>> Eric