views:

915

answers:

2

This method returns some strange results, and was wondering if someone could explain why this is happening, and possibly a solution to get my desired results.

Results:

FileName = what I'd expect

FileSize = what I'd expect

Buffer = all bytes = 0

BytesRead = 0

BlobString = string of binary data

FieldType = BLOB (what I'd expect)

ColumnType = System.String

Furthermore, if the file is greater than a few KB, the reader throws an exception stating the StringBuilder capacity argument must be greater than zero (presummably because the size is greater than Int32.MaxValue).

I guess my question is how does one properly read large BLOBs from an OdbcDataReader?

    public static String SaveBinaryFile(String Key)
    {
        try
        {
            Connect();

            OdbcCommand Command = new OdbcCommand("SELECT [_filename_],[_filesize_],[_content_] FROM [_sys_content] WHERE [_key_] = '" + Key + "';", Connection);
            OdbcDataReader Reader = Command.ExecuteReader(CommandBehavior.SequentialAccess);

            if (Reader.HasRows == false)
                return null;

            String FileName = Reader.GetString(0);
            int FileSize = int.Parse(Reader.GetString(1));
            byte[] Buffer = new byte[FileSize];
            long BytesRead = Reader.GetBytes(2, 0, Buffer, 0, FileSize);

            String BlobString = (String)Reader["_content_"];
            String FieldType = Reader.GetDataTypeName(2);
            Type ColumnType = Reader.GetFieldType(2);

            return null;
        }
        catch (Exception ex)
        {
            Tools.ErrorHandler.Catch(ex);
            return null;
        }
    }
A: 

Is the field type in the database definitely a BLOB rather than a CLOB? It certainly looks as if it's treating it as text data instead of binary data. What does Reader.GetFieldType(2) return?

Just as a side-issue, is the filesize field really a string rather than an integer? Can you not just use Reader.GetInt32(1)?

Finally, with your size issue - when you talk about something being "more than a few KB" - there's a big difference between "more than a few K" and "big enough to overflow int.MaxValue" (which would be 2GB). Do you have anything of a few megabytes in size?

Jon Skeet
A: 

I created the field as a BLOB. However, seeing the results of your suggestion of GetFieldType being a System.String, I'm not sure. I'm using the SQLite Manager FireFox addon to manager, and it's reporting content as a BLOB.

.NET and the SQLite manager seem to be conflicting. I can save the file properly out of the manager so I know it's stored properly -- it's just reading it into my app.

filesize is a text field, it was something I just quickly added to try to debug this whole thing and I plan to change it sooner or later.

The size issue is really surprising to me, but I cannot explain it (which is why I'm here :) I can't determine what the exact size limit is, but I know it will throw an error with a file that is only 34KB. Attached below is a copy of the exception report I generate.

Error Occured: 1:36 PM 1/4/2009 HelpLink:

InnerException:

Message:
'capacity' must be greater than zero. Parameter name: capacity

Source:
mscorlib

StackTrace:
at System.Text.StringBuilder..ctor(String value, Int32 startIndex, Int32 length, Int32 capacity) at System.Text.StringBuilder..ctor(String value, Int32 capacity) at System.Data.Odbc.OdbcDataReader.internalGetString(Int32 i) at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i, TypeMap typemap) at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i) at System.Data.Odbc.OdbcDataReader.get_Item(String value) at AppEx.Data.DatabaseHandler.SaveBinaryFile(String Key) in ...\Data\DatabaseHandler.cs:line 249

TargetSite:
Void .ctor(System.String, Int32, Int32, Int32)