提问人:Joshua Carmody 提问时间:10/23/2008 最后编辑:Joshua Carmody 更新时间:7/30/2009 访问量:4123
为什么 OdbcCommand.ExecuteScalar() 会抛出 AccessViolationException?
Why is OdbcCommand.ExecuteScalar() throwing an 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 并跳过第二个查询。实际上,我最初是这样做的,并且在getItemsCommand.GetString()中遇到了相同的错误。我担心数据集占用了太多内存,也许这导致了错误。所以我决定尝试这种方法,看看它是否有帮助。但事实并非如此。有谁知道为什么会发生这种情况?
顺便说一下,ID 是 INT 和 ITEMDESCRIPTION 是 VARCHAR(32000) 列。如果有什么区别,数据库是 Borland Interbase 6.0 (Ick!
编辑:在描述异常被抛出的位置时,我给出了错误的行!啊!!现已修复。另外,到目前为止,我已经尝试了建议的方法,但它们没有帮助。但是,我发现只有数据库中非常旧的记录导致了这个错误,这很奇怪。如果我将查询更改为仅拉取过去 5 年中插入的记录,则没有问题。有人向我建议这可能是编码转换问题或类似问题?
更新:解决了。事实证明,该问题是我们不太可靠的数据库软件的ODBC驱动程序中的错误。使用其他驱动程序的解决方法解决了该问题。
答:
在黑暗中开枪......
尝试执行读取器,保存结果(可能在数组或列表中),并确保读取器在执行或准备下一个命令之前已关闭。你甚至可能想走极端,把你的getItemsCommand构造放在一个using块中,这样你就知道在你执行下一个命令之前它没有打开的资源......
评论
这可能是您正在使用的 ODBC 驱动程序中的错误。它是什么驱动程序?您的连接字符串是什么?
评论