OleDbException (0x80004005): 未知错误

4

我有以下代码(作为Windows Form的一部分),在我的电脑上可以成功连接到Excel文件,但在另一台电脑上失败了。

var fd = new OpenFileDialog();
if (fd.ShowDialog() == DialogResult.OK)
{
    var extendedProperties = string.Empty;
    if (fd.FileName.Contains(".xlsx"))
    {
        // excel 2007 xml format file, IMEX = import data as text avoids data conversion errors
        extendedProperties = "Excel 12.0 Xml;IMEX=1";
    }
    else if (fd.FileName.Contains(".xls"))
    {
        // excel 2003 format file, IMEX: import data as text avoids data conversion errors
        extendedProperties = "Excel 8.0;IMEX=1";
    }

    var connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + fd.FileName + "';Extended Properties='" + extendedProperties + "'";
    using (var objXConn = new OleDbConnection(connectionString))
    {
        objXConn.Open();

        var selectStatement = string.Format("SELECT * FROM [tabName$] WHERE FormType IS NOT NULL");
        var dataTable = new DataTable("test");
        using (var objCommand = new OleDbCommand(selectStatement, objXConn))
        {
            var dataReader = objCommand.ExecuteReader();
            if (dataReader != null)
            {
                dataTable.Load(dataReader);
            }
        }
        using (var stringWriter = new StringWriter())
        {
            dataTable.WriteXml(stringWriter);
            this.textBox1.Text = stringWriter.ToString();
        }
    }
}

行为可以通过使用 OleDbDataAdapter 而不是 OleDbCommand.ExecuteReader() 来重现。
using (var dataAdapter = new OleDbDataAdapter(selectStatement, objXConn))
{
    dataAdapter.Fill(dataTable);
}

所谓失败,是指在 dataTable.Load(dataReader); 这一行发生以下错误。

在 x86 配置下运行 / 构建程序时,我遇到了以下错误。

System.Data.OleDb.OleDbException (0x80004005): Unknown
   at System.Data.OleDb.OleDbDataReader.ProcessResults(OleDbHResult hr)
   at System.Data.OleDb.OleDbDataReader.GetRowHandles()
   at System.Data.OleDb.OleDbDataReader.ReadRowset()
   at System.Data.OleDb.OleDbDataReader.Read()
   at System.Data.Common.DataAdapter.FillLoadDataRow(SchemaMapping mapping)
   at System.Data.Common.DataAdapter.FillFromReader(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 startRecord, Int32 maxRecords, DataColumn parentChapterColumn, Object parentChapterValue)
   at System.Data.Common.DataAdapter.Fill(DataTable[] dataTables, IDataReader dataReader, Int32 startRecord, Int32 maxRecords)
   at System.Data.Common.LoadAdapter.FillFromReader(DataTable[] dataTables, IDataReader dataReader, Int32 startRecord, Int32 maxRecords)
   at System.Data.DataTable.Load(IDataReader reader, LoadOption loadOption, FillErrorEventHandler errorHandler)
   at ExcelTest.Form1.button1_Click(Object sender, EventArgs e)
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

在使用AnyCPU/x64配置运行/构建程序时,我在两台机器上都遇到了以下错误。
System.InvalidOperationException: The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.
   at System.Data.OleDb.OleDbServicesWrapper.GetDataSource(OleDbConnectionString constr, DataSourceWrapper& datasrcWrapper)
   at System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString constr, OleDbConnection connection)
   at System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionInternal.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.OleDb.OleDbConnection.Open()
   at ExcelTest.Form1.button1_Click(Object sender, EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

被用于测试的Excel文件在两台机器上都是相同的。我已经能够使用多个文件(包括 .xls 和 .xlsx)重现该问题。
我已尝试以下措施来解决这个问题: 还可以采取哪些额外步骤来进行故障排除或解决此问题?

1
那么它实际上在哪一行崩溃了?我上周遇到了类似的问题,我将项目属性从anyCPU更改为运行x86,解决了类似的问题。 - MethodMan
1
文件在两台机器上是一样的吗?错误发生在dataTable.Load调用时。 - Steve
1
你有没有考虑在你的情况下使用SqlDataAdapterOleDataAdapter呢?与其使用Load,你可以利用Fill()方法。 - MethodMan
1
这是E_FAIL。这只是教师对错误报告质量的评分,它并没有说明失败的确切原因。 - Hans Passant
@MethodMan 我更新了问题。现在可以使用OleDbDataAdapter而不是OleDbCommand来重现它。 - Ryan Gates
显示剩余5条评论
1个回答

2

对于第一个问题,使用 OleDbDataAdapterFill() 方法或 Update() 方法。

        DataTable newTbl = new DataTable()
        using(OleDbDataAdapter ad = new OleDbDataAdapter(
            @"SELECT * FROM [tabName$] WHERE FormType IS NOT NULL", objXConn))
        {
           OleDbCommandBuilder builder = new OleDbCommandBuilder(ad);

           builder.QuotePrefix = "[";
           builder.QuoteSuffix = "]";

           // Saves the data set
           ad.Update(newTbl);
        }

32位和64位应用程序的OLEDB驱动程序是不同的。

如果你只安装了32位驱动程序,那么64位应用程序尝试使用它将会得到这个错误:Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine。同样,如果你只安装了64位版本,32位应用程序尝试使用它也会得到这个错误。

为了理解发生了什么,你应该检查你的应用程序。我认为这行代码可以帮助你:Environment.Is64BitProcess

如果xls(Excel 2003)文件出现问题,请尝试使用JET连接字符串!

编辑: 这里是两个驱动程序的链接:


使用FillUpdateLoad相比有哪些优势?这是否导致了问题?我已经能够使用Fill重现该问题。我将尝试Update。如何检查我安装了哪个(32位还是64位)驱动程序?我已经安装了来自链接的那些驱动程序。无论它们是什么,x86或x64版本都应该可以工作,对吗?在哪里可以找到适用于32位和64位系统的驱动程序?我已经能够为xlsxlsx文件重现该问题。 - Ryan Gates
这是http://www.microsoft.com/en-us/download/details.aspx?id=13255的链接,包含两个驱动程序。我假设您有x32位驱动程序,因为在x64上运行项目时会收到此错误。 - mybirthname
由于安装了32位的Office,我不得不使用32位版本。您能将上面的链接添加到答案中吗?一旦我安装了它,似乎就可以工作了。您能否详细说明为什么我应该使用OleDbDataAdapter和Fill()方法或Update()而不是Load()? - Ryan Gates
链接已添加,我使用OleDbDataAdapter,因为它比其他方法更加“灵活”。 - mybirthname

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接