0

如此处所述我正在使用 C# 将表从 SQL Server 重建到 Access 多亏了我收到的帮助,我可以完成该过程,但由于 .accdb 文件非常大,我需要在之后压缩和修复它们。为此,我使用了此处的标记答案。奇怪的是,我只能将“Microsoft Office 16.0 Access Database Engine Object Library”的引用添加到我的项目中。

using Microsoft.Office.Interop.Access.Dao;

var engine = new DBEngine(); // Exception
var destFile = Path.GetFileNameWithoutExtension(filepath) + "_Compact" + ".accdb";
var destFilePath = Path.Combine(Path.GetDirectoryName(filepath), destFile);

engine.CompactDatabase(filepath, destFilePath);

在初始化 DBEngine - 对象时,抛出异常:

Retrieving the COM class factory for component with CLSID {CD7791B9-43FD-42C5-AE42-8DD2811F0419} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).

另外,有没有办法使用 ADOX 来完成这项任务,因为我已经在使用它来创建我的目录?

4

1 回答 1

3

不幸的是,JRO、ADO 和 ADOX 都不能用于压缩和修复 Microsoft Access .accdb(Access 2007 及更高版本)数据库文件。但是,通过使用 DBEngine 对象,您走在了正确的轨道上。您可以用来避免依赖 PIA 的一种方法是在 ACE DAO 引擎上使用后期绑定(它取代了旧的 .mdb 格式的 JET DAO 引擎)。

此方法不需要 PIA 或项目参考。但它确实需要在机器上安装 ACE 引擎。ACE 可免费分发,可从 Microsoft 下载 - Microsoft Access Database Engine 2010 Redistributable

using System;

// Use ACE DAO to Compact an Access .ACCDB file
// This method uses late binding to create the ACE DAO.DBEngine object
public bool CompactDatabaseACE(string SourceDb, string TempPath)
{
    string Temp1Db, Temp2Db;
    object[] oParams;
    bool retVal = false;

    Temp1Db = Path.Combine(TempPath, Path.GetFileNameWithoutExtension(SourceDb) + ".cmp");
    Temp2Db = Path.Combine(Path.GetDirectoryName(SourceDb),Path.GetFileNameWithoutExtension(SourceDb) + ".old");
    if (File.Exists(Temp1Db))
        File.Delete(Temp1Db);
    if (File.Exists(Temp2Db))
        File.Delete(Temp2Db);
    oParams = new object[]
    {
        SourceDb, Temp1Db
    };
    try
    {
        object DBE = Activator.CreateInstance(Type.GetTypeFromProgID("DAO.DBEngine.120"));
        DBE.GetType().InvokeMember("CompactDatabase", System.Reflection.BindingFlags.InvokeMethod, null, DBE, oParams);
        if (File.Exists(Temp1Db))
        {
            try
            {
                File.Move(SourceDb, Temp2Db);
            }
            catch { }
            if (File.Exists(Temp2Db))
            {
                try
                {
                    File.Move(Temp1Db, SourceDb);
                }
                catch { }
                if (File.Exists(SourceDb))
                {
                    retVal = true;
                }
            }
            if (File.Exists(Temp1Db))
                File.Delete(Temp1Db);
            if (File.Exists(Temp2Db))
                File.Delete(Temp2Db);
        }
        System.Runtime.InteropServices.Marshal.ReleaseComObject(DBE);
        DBE = null;
    }
    catch (Exception ex)
    {
        // Do something with the error
    }
    return retVal;
}
于 2017-11-22T17:03:21.740 回答