OdbcCommand.ExecuteScalar()がAccessViolationExceptionをスローするのはなぜですか?
質問
データベーステーブルからテキストの説明を取得し、テキストファイルに保存するためのコードブロックがあります。次のようになります(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();
このコードはデータの一部を.txtファイルに正常に保存しましたが、多くの行では、AccessViolationExceptionが次の行でスローされます。
String description = (String)getDescriptionCommand.ExecuteScalar();
例外テキストは"保護されたメモリの読み取りまたは書き込みを試みました。多くの場合、これは他のメモリが破損していることを示しています。
プログラムは通常、テーブルの同じ行で例外をスローしますが、100%一貫性があるようには見えません。過去に例外をスローしたデータが突然機能する場合があります。
一部の人々は、なぜgetItemsCommandでID、ITEMDESCRIPTION FROM ITEMSだけを選択し、2番目のクエリをスキップしなかったのか疑問に思っています。実際、最初はそのようにしていたのですが、getItemsCommand.GetString()で同じエラーが発生していました。データセットがメモリを大量に消費し、それが原因でエラーが発生したのではないかと心配しました。そこで、この方法を試して、それが役立つかどうかを確認することにしました。しませんでした。なぜこれが起こっているのか誰にも分かりますか?
ところで、IDはINTで、ITEMDESCRIPTIONはVARCHAR(32000)列です。何らかの違いがある場合、データベースはBorland Interbase 6.0(Ick!)です
編集:例外がスローされた場所を説明するときに間違った行を指定しました!!ああ!!修正されました。また、これまでに提案したことを試しましたが、助けにはなりませんでした。しかし、データベース内の非常に古いレコードのみがこのエラーの原因であることがわかりました。これは奇妙です。過去5年間に挿入されたレコードのみをプルするようにクエリを変更しても、問題はありません。誰かがこれをエンコード変換の問題かそのようなものだと示唆しましたか?
更新:解決しました。この問題は、非常に信頼性の低いデータベースソフトウェアのODBCドライバーのバグであることが判明しました。他のドライバーの回避策により問題が修正されました。
解決
使用しているODBCドライバーのバグである可能性があります。それは何のドライバーですか?接続文字列は何ですか?
他のヒント
ここで暗闇でのショット...
次のコマンドを実行または準備する前に、リーダーを実行して結果を(おそらく配列またはリストに)保存し、リーダーが閉じていることを確認してください。次のコマンドを実行する前にリソースが開いていないことがわかるように、極端に進んでgetItemsCommand構造をusingブロック内に配置することもできます...