OleDbDataAdapter 在使用包含 Join 的语句时抛出 AccessViolationException

Posted

技术标签:

【中文标题】OleDbDataAdapter 在使用包含 Join 的语句时抛出 AccessViolationException【英文标题】:OleDbDataAdapter throwing AccessViolationException when using statment including a Join 【发布时间】:2017-08-15 20:30:26 【问题描述】:

我有一段旧代码直到上周都在工作。它使用 OleDb 帮助程序类来查询 MS Access 数据库。我已经能够指出特定查询的错误。经过一些实验,我可以确认当语句包含 JOIN 子句时,OleDataAdapter.Fill([DataSet]) 行会引发 AccessViolationException。我已经成功地从 Access 文件中运行了完全相同的查询。以及通过帮助程序类进行的其他更简单的查询。

什么可能导致此异常?我的研究没有为我提供任何见解,它似乎是一个通用的,“出了点问题”堆栈跟踪显示它起源如此之深以至于无法访问

StackTrace: 
at System.Data.Common.UnsafeNativeMethods.ICommandText.Execute(IntPtrpUnkOuter, Guid& riid, tagDBPARAMS pDBParams, IntPtr& pcRowsAffected,Object& ppRowset)
at System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS dbParams, Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior, Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method)
at System.Data.OleDb.OleDbCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.OleDb.OleDbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet)
at OleDatabase.hGetDS(String strSQL) in OleDatabase.cs:line 78
at GunTester.ServiceTest.getSalesOrder(String value) in ServiceTest.cs:line 53
at GunTester.ServiceTest.Manual() in ServiceTest.cs:line 29

GunTester 是我的测试类,OleDatabase 是辅助类。

我怀疑环境发生了某种变化,但据这里的任何人所知,托管此代码的服务器在错误出现之前的几天都没有被触及。代码同样没有被编辑。运行此代码的服务每天被调用数十次。

编辑:

这是一个条带化的代码块,删除了辅助类和所有其他层。该查询包含一个内部联接。我也看到左连接会发生这种情况,但在审查时,该查询将其作为子查询包含在内。如前所述,连接字符串指向 MS Access 数据库,错误由 da.Fill(A) 引发

public void MinimumTest()

        string joinCommand = "SELECT CI_I.ItemCode, IM_I.BinLocation FROM CI_Item CI_I INNER JOIN IM_ItemWarehouse IM_I ON (CI_I.DefaultWarehouseCode = IM_I.WarehouseCode) AND(CI_I.ItemCode = IM_I.ItemCode)";

        OleDbConnection conn = new OleDbConnection(ConfigurationManager.ConnectionStrings["RTMAS90"].ConnectionString);
        OleDbDataAdapter da = new OleDbDataAdapter(joinCommand, conn);

        DataSet A = new DataSet();
        da.Fill(A);

        Assert.AreEqual(1, A.Tables.Count);

情节扭曲: 我用虚拟数据创建了一些新的简单表

Table A     Table B
ID | This   ID | That
 1 | A       1 | A
 2 | C       2 | B 
 3 | E       3 | C

并在上述测试方法中使用了新查询

SELECT this,that FROM A INNER JOIN B ON A.id = b.id

这没有引发错误。这些新表与第一个失败示例中使用的表之间的区别在于它们的原始表是从MAS 200 链接的。

【问题讨论】:

你能想出一个minimal reproducible example吗?它是否仅因一个 JOIN 而失败,还是必须是一系列复杂的连接?内连接与外连接似乎对此有任何影响吗? @GordThompson:它在单个内部连接上失败,以及在选择中使用保存的查询的任何内容。内/外没有效果。 【参考方案1】:

在 MS Access 中,我使用链接表管理器刷新查询中的链接表,这解决了问题。

【讨论】:

以上是关于OleDbDataAdapter 在使用包含 Join 的语句时抛出 AccessViolationException的主要内容,如果未能解决你的问题,请参考以下文章

如何将准备好的语句与 OleDbDataAdapter 一起使用?

使用 vb.net、oledbdataadapter 更新数据库时出现问题

使用 Jet 的 OleDbDataAdapter 数据类型不匹配

是否有任何指示器可以知道OleDbDataAdapter是否根据提供的查询获得了记录?

如何使用 oleDbDataAdapter.Update(myDataSet) 更新 excel 文件

使用 OleDbDataAdapter 读取 CSV 文件时出现未指定的错误