views:

1552

answers:

3

I have a block of code intended to pull text descriptions from a database table and save them to a text file. It looks like this (C# .NET):

        OdbcCommand getItemsCommand = new OdbcCommand("SELECT ID FROM ITEMS", databaseConnection);
        OdbcDataReader getItemsReader = getItemsCommand.ExecuteReader();
        OdbcCommand getDescriptionCommand = new OdbcCommand("SELECT ITEMDESCRIPTION FROM ITEMS WHERE ID = ?", databaseConnection);
        getDescriptionCommand.Prepare();
        while (getItemsReader.Read())
        {
            long id = getItemsReader.GetInt64(0);
            String outputPath = "c:\\text\\" + id + ".txt";
            if (!File.Exists(outputPath))
            {
                getDescriptionCommand.Parameters.Clear();
                getDescriptionCommand.Parameters.AddWithValue("id", id);
                String description = (String)getDescriptionCommand.ExecuteScalar();
                StreamWriter outputWriter = new StreamWriter(outputPath);
                outputWriter.Write(description);
                outputWriter.Close();
            }
        }
        getItemsReader.Close();

This code has successfully saved a portion of the data to .txt files, but for many rows, an AccessViolationException is thrown on the following line:

                String description = (String)getDescriptionCommand.ExecuteScalar();

The Exception text is "Attempted to read or write protected memory. This is often an indication that other memory is corrupt".

The program will usually throw the exception on the same rows of the table, but it doesn't appear to be 100% consistent. Sometimes data that had thrown the exception in the past will suddenly work.

Some people are undoubtedly wondering why I didn't just SELECT ID, ITEMDESCRIPTION FROM ITEMS in the getItemsCommand and skip the second query. Actually, I did it that way initially, and I was encountering the same error with getItemsCommand.GetString(). I was afraid that perhaps the dataset was taking up too much memory and maybe that was causing the error. So I decided to try this method to see if it would help. It didn't. Does anyone know why this might be happening?

By the way, ID is an INT and ITEMDESCRIPTION is a VARCHAR(32000) column. If it makes any difference, the database is Borland Interbase 6.0 (Ick!)

EDIT: I gave the wrong line when describing where the exception was being thrown!! ARGH!! Fixed now. Also, I've tried the things suggested so far, but they didn't help. However, I found that only very old records in the database were causing this error, which is strange. If I change the query to only pull records inserted in the last 5 years, there are no problems. Someone suggested to me this might be an encoding conversion problem or something like that?

Update: Solved it. The problem turned out to be a bug in the ODBC driver for our not-very-reliable database software. A workaround with other drivers fixed the problem.

+1  A: 

A shot in the dark here...

Try executing your reader, saving your result (maybe in an array or list), and making sure the reader is closed before executing or preparing the next command. You may even want to go extreme and put your getItemsCommand construction inside a using block so you know that it has no resources open before you execute your next command...

Dave Markle
Tried, and it didn't help.
Joshua Carmody
Yeah... After hearing that closing the reader didn't help, I'd definitely try to get some support from the vendor on this one...
Dave Markle
+1  A: 

It could be a bug in the ODBC driver you are using. What driver is it? What is your connection string?

Joe
It's the Easysoft Interbase ODBC Driver. It's set up as a System DSN named "BVDATA2". The connection string in .NET is just "DSN=BVDATA2".
Joshua Carmody
It did, indeed, appear to be a bug with the ODBC driver.
Joshua Carmody
A: 

Hey! It worked for me :D .

Why would somebody not close an opened DataReader is beyond me, but still it worked. (Not my code, in case you were wondering...)

Now... in the other hand, why would not closing a DataReader provoke a AccessViolationException ? Any ideas why?

The problem turned out to be a bug in the ODBC driver for our not-very-reliable database software. A workaround with other drivers fixed the problem.
Joshua Carmody
Incidentally, what DataReader wasn't being closed? The last line of my code above is: getItemsReader.Close();
Joshua Carmody