从Access DB中读取附件:在此集合中找不到的项目

时间:2019-04-02 21:50:36

标签: c# ms-access office-interop

我有一个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的查看器中看到附件的内容)。 为此,我一直关注this answer:基本上,我想阅读附件并将其保存到进程文件夹中的文件中(以后将由另一个功能删除)。

这是我应该执行的方法(根据上表,输入templateName将是SpotHedgeUnwind ...):

    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(看不到内容,我也不知道为什么)。

如果我打开Access表,我可以看到正在寻找的附件(在这种情况下,我的fileNameSpot.xml

enter image description here

似乎我遗漏了一些明显的东西,但是我无法弄清楚自己在做错什么...任何进一步研究的提示?

1 个答案:

答案 0 :(得分:0)

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

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

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

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

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

我刚刚注意到,您链接到的另一个答案具有正确的字段名称,因此此代码中实际上没有任何显着差异。因此,该问题和答案仅是该问题的副本。