OleDB在64位模式下不支持吗?

15

我一直使用Microsoft.Jet.OLEDB.4.0和Microsoft.ACE.OLEDB.12.0来读取.csv,.xls和.xlsx文件。

我刚发现这两个技术都不支持本机64位模式!

我有两个问题:

  1. 在64位模式下以编程方式读取.csv,.xls和.xlsx文件的支持方式是什么?我找不到任何答案。

  2. 如果我不能同时读取这三种文件类型,在64位环境下读取.csv文件的最佳方法是什么?

注意事项:

  • 我正在使用.NET(3.5p1)
  • 这是一个收缩包应用程序;再分发是关键因素。

更新:

我可以使用CorFlags强制应用程序以32位模式运行,这样可以解决问题,但并不理想。

7个回答

8

这里讨论了关于已弃用的MDAC应该怎么做的问题。恐怕答案并不太令人满意...

这些新的或转换后的Jet应用程序可以继续使用Jet,以便在非主要数据存储中使用Microsoft Office 2003及更早版本的文件(.mdb和.xls)。但是,对于这些应用程序,您应该计划从Jet迁移到2007 Office System驱动程序。您可以下载2007 Office System驱动程序,它允许您读取和写入先前存在的Office 2003(.mdb和.xls)或Office 2007(*.accdb、*.xlsm、*.xlsx和*.xlsb)文件格式。重要提示:请阅读2007 Office System最终用户许可协议以获取特定的使用限制。
注意:SQL Server应用程序也可以通过2007 Office System驱动程序从SQL Server异构数据连接和集成服务功能访问2007 Office System和早期文件。此外,64位SQL Server应用程序可以通过在64位Windows上使用32位SQL Server集成服务(SSIS)来访问32位Jet和2007 Office System文件。

1
看起来2007 Office System Driver是正确的选择,不过25MB的下载有点大。 - Richard Szalay
我不确定2007 Office System Driver是否真的是x64,而不仅仅是JET的替代品...有人验证过吗? - Mark Brackett
不,它肯定是x86,因为我刚刚在尝试将SharePoint作为MSSQL x64中的链接服务器添加时遇到了这个限制。虽然与OP无关,但我解决问题的方法是安装一个单独的x86实例,该实例链接到Oledb源并用一堆视图包装它,而x64实例链接到x86实例。 - Josh

4
主要问题是Jet DBMS是一个32位的库,会被加载到调用进程中,所以您将无法直接在64位模式下从应用程序中使用Jet。正如Tim所提到的,您可以编写自己的csv解析器,但由于这是一个收缩包应用程序,您需要处理更广泛的格式。幸运的是,有许多方法可以与32位应用程序通信,因此您仍然可以使用Jet进行技巧操作。
我会编写一个标记为仅在32位模式下运行的小exe。这个exe将通过命令行参数获取要读取的文件名和要写入的临时文件名。我将使用Jet来加载csv/xls,然后将数据放入数组的数组中,并使用xml序列化器将数据写入临时文件。
然后当我需要加载/转换csv/xls文件时,我会执行以下操作:
object[][] ConvertFile(string csvOrXlsFile)
{
    var output = System.IO.Path.GetTempFileName();
    try
    {
        var startinfo = new System.Diagnostics.ProcessStartInfo("convert.exe",
            string.Format("\"{0}\" \"{1}\"", csvOrXlsFile, output));

        System.Diagnostics.Process proc = new System.Diagnostics.Process();
        proc.StartInfo = startinfo;

        proc.Start();
        proc.WaitForExit();

        var serializer = new System.Xml.Serialization.XmlSerializer(typeof(object[][]));
        using (var reader = System.IO.File.OpenText(output))
            return (object[][])serializer.Deserialize(reader);
    }
    finally
    {
        if (System.IO.File.Exists(output))
            System.IO.File.Delete(output);
    }
}

1
我喜欢这个选项,它尽可能地保持干净。将扁平文件转换为内部数据对象通常不需要运行x64;但是,一旦你将数据放入内部数据对象中,你可能想利用x64的优势。 - Nate

4

SpreadsheetGear for .NET可以读写.csv / .xls / .xlsx工作簿(以及更多),支持64位.NET 2.0+。SpreadsheetGear可以与WinForms或ASP.NET一起使用。您可以在此处查看ASP.NET(C#和VB)实时示例,了解有关WinForms示例的信息此处,如果您想自己尝试,则可以在此处下载免费试用版。

免责声明:我拥有SpreadsheetGear LLC


听起来很有趣,乔。谢谢! - John Weldon

4
你可以尝试使用FileHelpers库来解析扁平文件。 它的效果非常好。

谢谢Christopher...我确实考虑过FileHelpers,但就我所知,将LGPL包含在商业代码库中仍然是不可取的... - John Weldon
根据FileHelpers处理Excel文件的源代码,它使用了AdoDB,该库仅限于32位应用程序。有关详细信息,请参见ExtractDataTable函数。 - Alex Nolasco
@AlexanderN 我没有看到源代码,但是我尝试使用64位应用程序读取Excel文件,它可以完美地工作。而我的自己编写的旧代码使用Ado时出现了相同的问题,抛出了异常。 - Samuel
这个库真不错,点赞!我喜欢它可以自动映射 Excel 文件的列与我的类属性;这节省了我很多时间! - Samuel

3
这篇文章是为那些可能遇到此问题的人提供信息(以及为了以后我自己如果遇到同样的问题而无法记住解决方法时)。虽然它有点模糊,但让我感到压力,所以也许它会帮助其他人...如果这是重复的(找不到),或者已经过时了(一些人没有最新和最好的奢侈品),对不起。
如果您正在尝试使用Jet 4.0来访问基于x64的服务器上的MS Excel文档(或其他数据文件),则会发现没有支持此组合。
唯一的解决方案是允许IIS在Windows 64上运行32位应用程序,并安装受支持的db提供程序。
您需要安装64位ODBC(MSDASQL)驱动程序,它充当桥梁: “Microsoft OLE DB Provider for ODBC(MSDASQL)是一种技术,允许基于OLEDB和使用OLEDB内部的ADO构建的应用程序通过ODBC驱动程序访问数据源。 MSDASQL是连接到ODBC而不是数据库的OLEDB提供程序。 MSDASQL随Windows操作系统一起提供,Windows Server 2008和Windows Vista SP1是第一个包含技术64位版本的Windows版本。” 下载链接:http://www.microsoft.com/downloads/details.aspx?FamilyID=000364db-5e8b-44a8-b9be-ca44d18b059b&displaylang=en 这一切都很顺利,但我遇到了两个让我困惑(和压力)的事情: 1)您需要在IIS Web服务扩展中允许32位ASP.Net - 阅读“http://www.textcontrol.com/blog/permalink/2006082101”以获取有关启用32位应用程序和IIS Web服务扩展设置的说明。 2)如果您正在使用IIS x64下的任何注册表键,则会添加一个新节点到注册表中 - Wow6432Node - 您需要将在x64下使用的任何相关键移动/复制到其中。 即我们曾经在HCLM \ Software \ CustomKey中存储的数据密钥在启用32位后不再可用。我们在Wow6432Node下重新创建了该密钥,一切正常。

3

太好了!我希望微软能尽快推出一些东西。 - John Weldon

1

实际上,我认为Linq是您解决此问题的最佳方案。

类似于...

IEnumerable<MyObj> ObjList = GetObjList(yourCSVFileNAme);

var qry = from o in ObjList
          where o.MyField == Something
          select o;

而你的 GetObjList 方法看起来像这样

Public IEnumerable<MyObj> GetObjList(string filename)
{
  // Obvioulsly you would have some actual validation and error handling
  foreach(string line in File.ReadAllLines(filename))
  {
    string[] fields = line.Split(new char[]{','});
    MyObj obj = new MyObj();
    obj.Field = fields[0];
    obj.AnotherField = int32.Parse(fields[1]);
    yield return obj;
  }
}

谢谢Tim!我希望能够避免自己编写CSV解析解决方案。我知道这不是什么高深的技术,但有时候它是相当微妙的。 - John Weldon
2
解析CSV文件并不像宣传的那么简单(括号中的文本,不同地区使用不同的分隔符等等),但是有很多CSV解析器可供选择。 - VVS

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