以编程方式访问“压缩和修复”

Posted

技术标签:

【中文标题】以编程方式访问“压缩和修复”【英文标题】:Access "Compact and Repair" programmatically 【发布时间】:2010-08-17 14:50:45 【问题描述】:

是否可以以某种方式以编程方式“压缩和修复”Access 数据库(使用 ADOX、使用 OleDbConnection 等)?

【问题讨论】:

DAO 对你没有好处?我手头有一些使用 DAO 的 VBScript。 欢迎在这里发布脚本.... 这是一篇旧文章,但对我来说是谷歌上的第一次点击。我刚刚了解到无法压缩和修复打开的数据库 - 相反,它必须在关闭时设置为压缩。请参阅this Stack Overflow post 关于该主题。 【参考方案1】:

我没有足够的代表来回复以前的“答案”,但我想提供一些可能对其他人有关 OP 问题的信息有所帮助。

多年来,我一直使用 JRO 方法从 VB.net 压缩/修复我的 Access 2000 数据库。每隔一段时间,我就有一个客户端设法破坏了数据库(通常是通过网络连接到数据库并且它们遭受意外的网络中断)。只要数据库没有损坏,JRO(根据我的经验)就可以正常工作。如果我使用 Access 应用程序来修复数据库,我永远无法弄清楚为什么可以修复数据库,但是当使用 MY 应用程序(使用 JRO)时,压缩/修复总是会失败(数据库的格式无法识别)。

所以,在一小时前遇到这个线程后,我将 DAO 的引用放到我的应用程序中,并尝试了它修复损坏数据库的能力,因为我今天刚刚有一个客户损坏了他们的数据库(第三次发生在大约 8 年)。猜猜看,当 JRO 失败时,DAO 能够修复数据库!

好的,这就是我对 JRO 与 DAO 的经验。希望能帮助到你。下面是一段使用 DAO 中的CompactDatabase 的示例代码:

Dim dbCorrupt As String = "c:\CorruptedDB.mdb"
Dim dbRepaired As String = Path.Combine(Path.GetDirectoryName(dbPath), Path.GetFileNameWithoutExtension(dbPath) & "_Repaired.mdb")

Dim dao As New dao.DBEngine
dao.CompactDatabase(dbCorrupt, dbRepaired)

【讨论】:

您在“添加引用”对话框中选择了哪个特定的 DAO 条目? Interop.DAO.dll 是我所引用的。不记得我在哪里得到的。您将不得不为此做一些调查。【参考方案2】:

在c#.net中只有四行代码

首先使用一个库:

using JRO;

您想使用以下代码压缩和修复test.mdb

string currentdirectory = System.IO.Directory.GetCurrentDirectory();
string oldmdbfile = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + currentdirectory + "\\test.mdb;Jet OLEDB:Database Password='xyz'";
string newmdbfile = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + currentdirectory + "\\test1.mdb;Jet OLEDB:Database Password='xyz'";
string oldmdbfilepath = currentdirectory + "\\test.mdb";
string newmdbfilepath = currentdirectory + "\\test1.mdb";

JRO.JetEngine engine = new JetEngine();
engine.CompactDatabase(oldmdbfile, newmdbfile);
File.Delete(oldmdbfilepath);
File.Move(newmdbfilepath, oldmdbfilepath);
MessageBox.Show("Database compact and repaired successfully !",);

因此test.mdb 将被压缩和修复,并创建一个新文件test1.mdb。然后你只需要删除test.mdb并将test1.mdb重命名为test.mdb

【讨论】:

【参考方案3】:

可以通过两种方式压缩和修复 MS ACCESS 数据库:

使用DAO:在DAO350中有一个方法RepairDatabase(),而在DAO360中有一个CompactDatabase() 使用 MDAC+JRO:

例如,在 VB6 (old, old, old...) 中这样做:

Dim jro As jro.JetEngine
Set jro = New jro.JetEngine
jro.CompactDatabase "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\db_to_repair.mdb;Jet OLEDB:Database Password=mypass", _ 
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\repaired_db.mdb;Jet OLEDB:Engine Type=4;Jet OLEDB:Database Password=mypass"

如您所见,该函数要求您指定要修复的数据库名称和已修复数据库的名称。

【讨论】:

DAO 比 JRO 好,我认为。 嗨 Remou,我恐怕无法就此给出明智的意见,你知道,我用过这两种技术,但我从未深入研究过这些技术。 从 Jet 3.51 中删除了修复,c。 1997 年。除了 Compact 之外,永远不要使用任何东西。【参考方案4】:

VBScript 的示例代码。

Dim objEngine
Dim objProcess
'Dim objDB
Dim strDb1

Dim strPath
Dim strFile
Dim strDAOversion
Dim strApplicationName
Dim strErr

Dim strMsg
Dim FSO

strPath = "C:\Docs\"

strFile = "Some.mdb"
strDb1 = strPath & strFile

Set FSO=CreateObject("Scripting.FileSystemObject")

strDAOversion = "DAO.DBEngine.36"
strApplicationName = "Some.mdb"

strMsg = "About to perform a COMPACT on "
strMsg = strMsg & chr(10) & chr(10)
strmsg = strMsg & strApplicationName
strMsg = strMsg & chr(10) & chr(10)
strmsg = strmsg & "Please ask everyone to EXIT THE SYSTEM."
strMsg = strmsg & chr(10) & chr(10)
strmsg = strmsg & space(12) & "It is VITAL you do not exit windows until"
strMsg = strMsg & chr(10)
strMsg = strMsg & space(12) & "you receive the confirmation message."
strMsg = strmsg & chr(10) & chr(10)
strMsg = strMsg & space(6) & "Press OK to continue or Cancel to stop the process."


If MsgBox(strMsg, 1, strApplicationName) = 1 Then

  Set objEngine = WScript.CreateObject(strDAOversion)

  Call CompactDB(FSO, objEngine, strDb1, "password")

  If strErr="True" Then
    strMsg = "Please correct the problem and try again."
    MsgBox strMsg, 1, strApplicationName
  Else
    strMsg = "Database compacting complete."
    MsgBox strMsg, 1, strApplicationName
  End If
End If


Function CompactDB(objFSO, objEngine, strDb, pwd)

'Compact the database

Dim strdbtemp
Dim MsgText

strdbtemp = Left(strDb, Len(strDb) - 3) & "ldb"

If FSO.FileExists(strdbtemp) = True Then 'if ldb file exists, db is still open.
MsgText = "You have not exited the file. Please close and try again."
MsgBox MsgText, 1, strApplicationName
strErr="True"
Exit Function
End If

If FSO.FileExists(strDb1) = False Then
MsgText = "Cannot locate the database at " & strDB
MsgBox MsgText, 1, strApplicationName
strErr="True"
Exit Function
End If

strdbtemp = Left(strDb, Len(strDb) - 3) & "tmp"

If pwd = "" Then
objEngine.CompactDatabase strDb, strdbtemp
Else
objEngine.CompactDatabase strDb, strdbtemp, , , ";pwd=" & pwd
End If

If Err = 0 Then
FSO.deletefile strDb
FSO.copyfile strdbtemp,strDb
FSO.deletefile strdbtemp
Else
MsgText = "Error during COMPACT process for " & strDB
MsgBox MsgText, 1, strApplicationName
strErr="True"
End If

End Function

【讨论】:

我立即看到该代码存在一个问题,那就是您正在检查 LDB 的存在以查看 MDB 是否打开,并且即使当MDB 未打开。要真正查看MDB是否打开,您应该尝试删除LDB,如果失败,则MDB已打开。 顺便说一句,我周一刚刚为此编写了一个脚本,以在服务器上作为计划任务运行。我记录了所有内容,而不是消息框。但是我的代码不如你的好。 我很确定我不能把大部分归功于我,但我已经有一段时间了,所以我也不能为相关部分分配信用。 strErr 除了“True”之外没有分配任何东西,所以如果它用于按位比较,它应该是一个布尔值。 啊,我明白了!所以 VBSCript 的类型非常弱 :) 可能不是使用 "True" 而是将它用作 true 会更好,我相信即使你不能强烈地键入对象,布尔赋值也应该起作用。 boolErr = true【参考方案5】:

此解决方案适用于 Access 2010 数据库引擎:

必填参考:

Microsoft.Office.interop.access.dao

代码:

public void CompactDb(
    string sourceFilePath, string destFilePath, string password)

    var dbEngine = new Microsoft.Office.Interop.Access.Dao.DBEngine();

    dbEngine.CompactDatabase(sourceFilePath, destFilePath,
        ";pwd=" + password, null, ";pwd=" + password);

(sourceFilePath 和 destFilePath 不能相同!)

CompactDatabase 方法参数(来自反射):

void CompactDatabase(
    string SrcName, string DstName,
    object DstLocale = Type.Missing,
    object Options = Type.Missing,
    object SrcLocale = Type.Missing);

确保您在与您安装的 AccessDatabaseEngine(或 Office)相同的平台下运行它 (x86/x64)。

【讨论】:

【参考方案6】:

这是官方的 MS 链接,任何进一步的 cmets 都是多余的。 DBEngine.CompactDatabase Method

【讨论】:

【参考方案7】:

添加参考:Microsoft ActiveX Data Objects 2.x Library Microsoft Jet 和复制对象 2.x 库

sDB = "c:\DB\myDb.mdb"
sDBtmp = "c:\DB\tempMyDb.mdb"
sPASSWORD = "password"

Dim oApp As Access.Application
Set oApp = New Access.Application
Call oApp.DBEngine.CompactDatabase(sDB, sDBtmp, dbLangGeneral, , ";pwd=" & sPASSWORD)

'wait for the app to finish
        DoEvents
'remove the uncompressed original
        Kill sDB
'rename the compressed file to the original to restore for other functions
        Name sDBtmp As sDB

【讨论】:

以上是关于以编程方式访问“压缩和修复”的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 的线程中以编程方式复制 Excel 文件时修复访问拒绝错误

如何使用 Python 3 压缩和修复 Access 数据库

经常压缩和修复 Access DB 是不是安全?

C# 使用 DAO 或 ADOX 压缩和修复 .accdb 文件

通过压缩和修复从 Cassandra db 中删除大量数据后,磁盘空间未更改

如何等待 Compact Repair - 访问 VBA