65.9K
CodeProject 正在变化。 阅读更多。
Home

Access 数据库的奇怪行为

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (11投票s)

2006 年 8 月 20 日

CPOL

5分钟阅读

viewsIcon

48768

downloadIcon

1224

我建议所有不知道Microsoft Access MDB文件安全(特别是压缩和修复)的人,在为时已晚之前阅读本文!

警告:上面的源文件只能与Access 2002、2003和Jet Engine 4一起使用。将它们与任何其他版本一起使用都会损坏数据库。

Sample Image - cmpct_scshot1.jpg

引言

不久前,我遇到了一个应用程序中的奇怪行为,该应用程序正在使用Access数据库(*.mdb 文件)。我在CodeProject C++论坛上发了一个问题,但没有得到任何答复。我开始在网上、MSDN等地方搜索……我发现这并非全是我的错。我在一个知识库文章中找到了原因。看看它关于Access数据库文件可能损坏的描述。

"在Access内部和外部,有许多事情可能会导致数据库文件损坏。损坏的数据库的症状可能包括在某些记录中出现#Deleted,或者您无法打开数据库中的某个对象,甚至无法在Access中打开数据库文件。"(MSDN-知识库:283849)

由于我在论坛上没有得到问题的答案,我认为至少有一些人可能不知道这一点,而且由于MDB文件很容易损坏,而要理解应用程序为何运行不正常却很难,所以我开始写这篇文章。

问题是,什么可能导致Access MDB文件损坏,以及如何以编程方式修复损坏的Access文件?

背景

什么可能导致MDB文件损坏

知识库称:

"MDB 文件可能损坏有三个主要原因,如下所示:

  • 中断的写入操作
  • 有故障的网络硬件
  • 在其他程序中打开和保存MDB文件"(MSDN-知识库:283849)

知识库中对其中每一项都有详细的描述,但一些重要的原因如下:

  • 数据库写入期间断电
  • 网络连接中断
  • Microsoft Jet 连接异常终止,例如通过任务管理器强制关闭应用程序、断电、手动关机。(请注意:致命系统错误几乎总是导致异常终止,请参考KB以获取更多信息)
  • 忘记关闭打开的ADO或DAO对象(来自类如:RecordsetQueryDefTableDefDatabase的对象)
  • 大量的打开和关闭操作在循环中进行(超过40,000次连续的打开和关闭操作可能导致损坏)
  • 最糟糕的是,在Microsoft Word等其他程序中**打开**和**保存**MDB文件。这无法恢复。您所有的数据都将丢失。

"在不同的程序中打开并保存的MDB文件无法恢复"
(MSDN-知识库:283849)

如何减少损坏的可能性

  • 避免以上所有情况
  • 经常压缩数据库(本文提供的类)

情况可能会变得更糟

Q291162:压缩和修复数据库后,自动编号字段重复之前的值:Microsoft还宣布,在压缩和修复数据库后,可能会遇到自动编号字段重复的问题,如果这是您的数据库主键,那么……
幸运的是,这仅适用于使用Microsoft Jet版本4.0.2927.4及更早版本的用户。"Microsoft已确认这是Microsoft Jet版本4.0.2927.4及更早版本中的一个问题。"(Microsoft KB Q291162)。要查找您的Jet引擎版本,请尝试在您的system/32目录中搜索Msjet40.dll(如果您使用的是v.4及更高版本),然后获取文件的属性。此KB可以帮助您找到您的版本并下载最新版本:Q239114。

还存在另一个错误:“压缩Access数据库后,自动编号字段未重置”。我没有对此给出解决方案,因为已经有了,而且它也不是真正关键的问题。有关更多信息,请参考知识库Q287756。

如果您丢失了数据并且在恢复数据时遇到问题(仍然存在),这可以为您提供很大的帮助:Q247771和Q306204。

Using the Code

要使用该代码,请按照以下步骤操作:

  1. DBFitter.cppDBFitter.h复制到您的项目中。
  2. DBFitter.cpp中检查并可能更改前两个#import 指令。
    #import "D:\PROGRAM FILES\COMMON FILES\System\ado\msado15.dll" 
    	rename( "EOF", "MSADO_EOF" )
    #import "D:\PROGRAM FILES\COMMON FILES\System\ado\MSJRO.DLL" no_namespace
  3. 包含DBFitter.h,创建一个类型为DBFitter 的对象,并按如下方式使用它:
     CDBFitter fitter;
     if ( !fitter.CompactAndRepair(szDbPath,m_szDBPass) ) {
        AfxMessageBox(fitter.GetLastErrString());
     }   

    CompactAndRepair 有三种形式可以交替使用。您上面看到的第一种形式,另一种形式只接受数据库文件路径作为输入,并且不使用密码。

    CompactAndRepair(CString szDbPath)    

    最后一种形式要求提供源、目标和密码,密码可以为空字符串"",表示没有密码。

    CompactAndRepair(CString szSrcDbPath, CString szDstDbPath, CString szDbPassword)
  4. 别忘了在应用程序的初始化中调用AfxOleInit();

"在运行压缩和修复实用程序之前,请确保以下事项:

在运行数据库的压缩和修复实用程序之前,请确保以下事项:

  • 请确保您的硬盘上有足够的可用存储空间来存放Access数据库的原始版本和压缩后的版本。这意味着您必须在该驱动器上拥有至少两倍于Access数据库大小的可用存储空间。如果您需要释放一些空间,请删除该驱动器上任何不需要的文件,或者,如果可能,将Access数据库移动到具有更多可用空间的驱动器上。
  • 请确保您对Access数据库具有“打开/运行”和“独占打开”权限。如果您是数据库的所有者,请确保设置这些权限。如果您不是数据库的所有者,请联系其所有者,了解是否可以获得这些权限。
  • 请确保没有用户打开了Access数据库。
  • 请确保Access数据库未位于只读网络共享上,或者其文件属性未设置为“只读”。"(Q283849)

C# 中的压缩和修复

感谢上帝,已经有一篇文章了。

© . All rights reserved.