首页 > 解决方案 > 从 Access DB 读取附件:在此集合中找不到项目

问题描述

我有一个 Access 数据库 ( @"Provider=Microsoft.ACE.OLEDB.12.0),其中包含一个名为FTLH_DBF. 该表的结构如下:

+----+--------+--------+--------+--------------------------+
| ID | M_TYPE | M_NAME | M_DESC |          M_FILE          |
+----+--------+--------+--------+--------------------------+
|  1 |      0 | Spot   | Blabla | (Attachment: Spot.xml)   |
|  2 |      1 | Hedge  | Blabla | (Attachment: Hedge.xml)  |
|  3 |      2 | Unwind | Blabla | (Attachment: Unwind.xml) |
+----+--------+--------+--------+--------------------------+

按照设计,代码确保附件名称M_FILE等于M_NAME+ .xml,并且在表中找不到重复项M_NAME

我正在尝试在保存附件后重新读取附件(成功地,我可以在 Access 的查看器中看到附件的内容)。为了做到这一点,我一直在关注这个答案:基本上我想阅读附件并将其保存到进程文件夹中的文件中(稍后将被另一个函数删除)。

这是我应该这样做的方法(templateName根据上表,输入将是Spot, Hedge, Unwind...):

    public void dumpAttachmentToFile(string templateName)
    {
        string fileName = templateName + ".xml";
        var dbe = new DBEngine();
        Microsoft.Office.Interop.Access.Dao.Database db = dbe.OpenDatabase(DB_LOCATION);
        Recordset rstMain = db.OpenRecordset(
                "select M_FILE from FTLH_DBF where M_NAME = '" + templateName + "';",
                RecordsetTypeEnum.dbOpenSnapshot);
        Recordset2 rstAttach = rstMain.Fields["M_FILE"].Value;
        while ((!fileName.Equals(rstAttach.Fields["M_FILE"].Value)) && (!rstAttach.EOF))
        {
            rstAttach.MoveNext();
        }
        if (rstAttach.EOF)
        {
            Console.WriteLine("Not found.");
        }
        else
        {
            Field2 fld = (Field2)rstAttach.Fields["M_FILE"];
            fld.SaveToFile(fileName);
        }
        db.Close();
    }

当我执行此代码时,我收到以下运行时错误:

System.Runtime.InteropServices.COMException
  HResult=0x800A0CC1
  Message=Item not found in this collection.
  Source=MxML-Factory
  StackTrace:
   at Microsoft.Office.Interop.Access.Dao.Fields.get_Item(Object Item)
   at MxML_Factory.Database.DBConnection.dumpAttachmentToFile(String templateName) in C:\Users\Matteo\source\repos\MxML-Factory\MxML-Factory\Database\DBConnection.cs:line 182
   at MxML_Factory.Business.MxML.Load(String m_name) in C:\Users\Matteo\source\repos\MxML-Factory\MxML-Factory\Business\MxML.cs:line 73
   at MxML_Factory.Utils.BrowseClassMapper.OpenFormInstance(Object TriggerClass, String loadingKey, DatabaseBrowse callback) in C:\Users\Matteo\source\repos\MxML-Factory\MxML-Factory\Utils\BrowseClassMapper.cs:line 24
   at MxML_Factory.WinForms.DatabaseBrowse.OpenInstance(String objectKey) in C:\Users\Matteo\source\repos\MxML-Factory\MxML-Factory\WinForms\DatabaseBrowse.cs:line 66
   at MxML_Factory.WinForms.DatabaseBrowse.HandleKeyPress(Object sender, KeyEventArgs e) in C:\Users\Matteo\source\repos\MxML-Factory\MxML-Factory\WinForms\DatabaseBrowse.cs:line 91
   [...previous calls of the stack which cannot be guilty...]

...在以下代码行:

while ((!fileName.Equals(rstAttach.Fields["M_FILE"].Value)) && (!rstAttach.EOF))

该对象rstAttach包含一个集合Fields,但我只能在其中看到一个属性count = 6(看不到内容,我不知道为什么)。

如果我打开我的访问表,我可以看到有我正在寻找的附件(在这种情况下,我fileName的是Spot.xml

在此处输入图像描述

似乎我遗漏了一些明显的东西,但我无法弄清楚我做错了什么......有什么提示可以进一步调查吗?

标签: c#ms-accessoffice-interop

解决方案


有关VBA 中的示例(可轻松转换为 C# 互操作代码),请参阅Microsoft Docs for Field2.SaveToFile 方法。

主记录集的字段中的子记录M_FILE集包含一组特定的字段名称。首先,您可以通过遍历字段集合并打印 Field2.Name 属性来发现这些。上面的链接表明至少有 2 个字段名称是FileNameFileData。缺点是循环应该是

while ((!rstAttach.EOF) && (!fileName.Equals(rstAttach.Fields["FileName"].Value, OrdinalIgnoreCase)))

此外,实际保存文件的行应该是

Field2 fld = (Field2)rstAttach.Fields["FileData"];
fld.SaveToFile(fileName);

我刚刚注意到您链接到的另一个答案具有正确的字段名称,因此此代码实际上没有什么明显不同。因此,这个问题和答案只是该问题的重复。


推荐阅读