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

以编程方式压缩和修复 Access 数据库(使用 C#)

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.84/5 (13投票s)

2007 年 3 月 20 日

CPOL

2分钟阅读

viewsIcon

115337

downloadIcon

1887

一种简单的方法,使用 Microsoft Jet 库和 C# COM interop 以压缩和修复 Microsoft Access 数据库文件。示例代码旨在集成到 ASP.NET 网站中。

引言

正如你们中的许多人所知,当数据被删除时,Microsoft Access 数据库不会自动缩小。相反,Access 文件会不断增长,直到用户要求应用程序压缩和修复数据库。(您可以告诉 Access 在最后一个用户关闭数据库时自动压缩和修复,但这并不能解决此处提出的问题。)如果您需要以编程方式管理 Access 文件怎么办?我们公司的软件会将数据写入 Access 文件,并允许用户下载它们。只有一个问题 - 每次我们写入文件时,即使我们首先截断表,它也会不断增长!我的任务是找到一种无需用户参与或运行 Access 即可以编程方式压缩和修复数据库的方法。经过一番搜索,我能够找到几个使用经典 ASP 和/或 VB6 完成此操作的示例。我采用了这些示例,将代码迁移到托管 C#,将其引入 ASP.NET 网站,并将该过程抽象为一个简单的实用函数。

背景

Microsoft 通过其 JET 框架提供了一种以编程方式压缩和修复数据库的方法。 JET 也是应用程序能够从 Microsoft Office 生态系统中的各种文件格式(包括 Access 和 Excel 文件)中读取和写入的方法。我们的应用程序使用 SQL Server Integration Services 通过 JET 提供程序将数据从 SQL Server 导出到 Access 数据库,然后用户通过 HTTP 下载该数据库。

Using the Code

该代码由一个位于 ASP.NET 网站的 App_Code 文件夹中的类中的 static 方法组成。该代码可以轻松地适应在桌面应用程序中运行 - 您只需要删除路径映射逻辑。

在编译此代码之前,需要执行一个关键步骤(别担心,这很简单)。向您的网站(或桌面应用程序)添加引用。在“添加引用”对话框中,转到 COM 选项卡。找到 Microsoft Jet 和复制对象库(DLL 文件是 msjro.dll),然后添加它。如果您正在使用网站,您会注意到 Visual Studio 将自动在您的 BIN 文件夹中创建几个互操作程序集。这些用于允许您的托管代码与涉及的 COM 对象进行通信。该过程是完全透明的 - 搜索 .NET COM Interop 以了解更多信息。

注意:以这种方式压缩数据库不一定可以并发执行。您需要根据需要实现并发和线程安全。

这是包含 XML 注释的代码(您也可以在上面下载它)

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.IO;
using JRO;

/// <summary>
/// Encapsulates small static utility functions.
/// </summary>
public class Utility
{
 /// <summary>The connection to use to connect to
 /// an Access database using JET.</summary>
 public const string AccessOleDbConnectionStringFormat =
  "Data Source={0};Provider=Microsoft.Jet.OLEDB.4.0;";

 /// <summary>
 /// Compacts an Access database using Microsoft JET COM
 /// interop.
 /// </summary>
 /// <param name="fileName">
 /// The filename of the Access database to compact. This
 /// filename will be mapped to the appropriate path on the
 /// web server, so use a tilde (~) to specify the web site
 /// root folder. For example, "~/Downloads/Export.mdb".
 /// The ASP.NET worker process must have been granted
 /// permission to read and write this file, as well as to
 /// create files in the folder in which this file resides.
 /// In addition, Microsoft JET 4.0 or later must be
 /// present on the server.
 /// </param>
 /// <returns>
 /// True if the compact was successful. False can indicate
 /// several possible problems including: unable to create
 /// JET COM object, unable to find source file, unable to
 /// create new compacted file, or unable to delete
 /// original file.
 /// </returns>
 public static bool CompactJetDatabase(string fileName)
 {
  // I use this function as part of an AJAX page, so rather
  // than throwing exceptions if errors are encountered, I
  // simply return false and allow the page to handle the
  // failure generically.
  try
  {
   // Find the database on the web server
   string oldFileName =
    HttpContext.Current.Server.MapPath(fileName);

   // JET will not compact the database in place, so we
   // need to create a temporary filename to use
   string newFileName =
    Path.Combine(Path.GetDirectoryName(oldFileName),
    Guid.NewGuid().ToString("N") + ".mdb");

   // Obtain a reference to the JET engine
   JetEngine engine =
    (JetEngine)HttpContext.Current.Server.CreateObject(
    "JRO.JetEngine");

   // Compact the database (saves the compacted version to
   // newFileName)
   engine.CompactDatabase(
    String.Format(
     AccessOleDbConnectionStringFormat, oldFileName),
    String.Format(
     AccessOleDbConnectionStringFormat, newFileName));

   // Delete the original database
   File.Delete(oldFileName);

   // Move (rename) the temporary compacted database to
   // the original filename
   File.Move(newFileName, oldFileName);

   // The operation was successful
   return true;
  }
  catch
  {
   // We encountered an error
   return false;
  }
 }
}

贡献者

感谢 Roy Fine、Craig Starnes 和 Michael Brinkley 之前在其他语言中对这个问题的研究。

历史

  • 2007 年 3 月 20 日 - 发布第一个版本
© . All rights reserved.