You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#操作Microsoft Access数据库后程序无法终止及内存报错问题

问题描述

我尝试使用如下C#代码读取Microsoft Access数据库。

static void getProducts()
{
    string accessDBPath = @"C:\Users\...\dummydb.accdb";
    string connectionString = @"Provider=Microsoft.ACE.OLEDB.16.0;Data Source=" + accessDBPath;
    string strSQL = "SELECT * FROM Products";
    try
    {
        using (OleDbConnection connection = new OleDbConnection(connectionString))
        {
           connection.Open();
           OleDbCommand command = new OleDbCommand(strSQL, connection);
           OleDbDataReader reader = command.ExecuteReader();
           while (reader.Read())
           {
               Console.WriteLine("product name = ...");
           }
        }
     }
     catch (OleDbException ex)
     {
         Console.WriteLine(ex.Message);
     } 
     finally
     {
         Console.WriteLine("Finished");
     }
}

我可以正常遍历Products表(即while(reader.Read()){...}块内的内容可按预期打印输出),finally块的内容也能正常打印执行。
但该函数执行完成后,程序始终无法终止,命令行窗口处于冻结无响应状态。当我尝试在Main函数末尾通过Environment.Exit(0);强制退出程序时,会收到如下错误:

尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

按照逻辑,using语句应当在数据库操作完成后自动关闭数据库连接,但实际表现仿佛连接并未被正确释放,无法定位问题原因。
编辑补充:已排查复制粘贴错误,不存在变量重复声明问题。


解决方案

核心原因

问题不是using对OleDbConnection的释放逻辑失效,而是你漏了释放OleDbCommand和OleDbDataReader持有的非托管资源。ACE OLEDB驱动是原生COM实现,OleDbDataReader会持有底层游标、数据库连接的原生内存引用,仅靠OleDbConnection的Dispose方法不会主动回收这部分资源。函数执行完成后,未释放的原生资源会在CLR卸载应用程序域时触发访问违例,直接表现就是程序卡死、强制退出时报内存受保护的错误。
除此之外,项目平台目标和ACE驱动位数不匹配、多版本ACE驱动共存也会触发完全相同的现象。

按以下步骤逐一排查修复即可:

  • 所有OLEDB相关的可释放对象全部用using块包裹,不要只包裹OleDbConnection。OleDbCommand、OleDbDataReader都实现了IDisposable接口,嵌套using可以保证所有非托管资源按顺序被正确释放,修正后的核心代码如下:
static void getProducts()
{
    string accessDBPath = @"C:\Users\...\dummydb.accdb";
    string connectionString = @"Provider=Microsoft.ACE.OLEDB.16.0;Data Source=" + accessDBPath;
    string strSQL = "SELECT * FROM Products";
    try
    {
        using (OleDbConnection connection = new OleDbConnection(connectionString))
        {
           connection.Open();
           using (OleDbCommand command = new OleDbCommand(strSQL, connection))
           using (OleDbDataReader reader = command.ExecuteReader())
           {
               while (reader.Read())
               {
                   Console.WriteLine("product name = ...");
               }
           }
        }
     }
     catch (OleDbException ex)
     {
         Console.WriteLine(ex.Message);
     } 
     finally
     {
         Console.WriteLine("Finished");
     }
}
  • 检查项目平台目标和安装的ACE驱动位数是否匹配。如果安装的是64位Access Database Engine,却把项目编译为x86(32位),或者反过来装了32位引擎编译为x64,会导致ACE驱动在原生层加载异常,即使查询能正常执行,程序退出时也会触发内存损坏错误。可以打开项目属性-生成页,把平台目标强制设置为和已安装ACE驱动一致的版本(x86或x64),不要使用"Any CPU"配置,同时取消勾选"首选32位"选项。
  • 如果上述修改后问题仍然存在,检查本机是否安装了多个版本的ACE OLEDB驱动(比如同时安装了2010版和2016版引擎,或者同时存在Office自带的引擎和独立安装的Database Engine包),版本冲突会导致原生DLL加载错乱,卸载多余版本只保留一个即可解决。

内容的提问来源于stack exchange,提问作者Daniel Xiao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 06:21:19