OleDB连接到Microsoft Access数据文件的间歇性“超出系统资源”异常

时间:2012-11-20 23:59:35

标签: c# ms-access oledb

运行我的代码时,我遇到了看似随机的“超出系统资源”异常。我的程序背后的想法是第三方软件不断将数据写入Microsoft Access数据库文件(.res) - 大约每30秒我的代码从此文件读取数据,做一些对它进行操作,并将结果写入我们的数据库。不幸的是,我无法改变第三方软件将数据写入文件的方式,我对Access数据文件感到困惑。

在运行通过Click-Once发布安装的WinForms程序的生产系统以及我的开发系统上的控制台测试程序中都会发生此错误。即使在运行返回单个整数的查询而没有其他程序或线程触及位于本地磁盘上的文件时,我也会收到异常。

异常信息:

System.Data.OleDb.OleDbException (0x80004005): System resource exceeded.
   at System.Data.OleDb.OleDbCommand.ExecuteCommandTextErrorHandling(OleDbHResult hr)
   at System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS dbParams, Object& executeResult)
   at System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object& executeResult)
   at System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior, Object& executeResult)
   at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method)
   at System.Data.OleDb.OleDbCommand.ExecuteScalar()
...

重现问题的示例代码:

string connectionString = @"Provider = Microsoft.ACE.OLEDB.12.0; Data Source = C:\datafile.res";
string commandText = "SELECT MIN(Data_Point) FROM Channel_Normal_Table WHERE Test_ID = 1";

int connectionCounter = 0;            
object result;

while (true)
{                
    using (OleDbConnection connection = new OleDbConnection(connectionString))
    {
        connection.Open();
        connectionCounter++;

        using (OleDbCommand command = new OleDbCommand(commandText, connection))
        {
            result = command.ExecuteScalar();
        }

        connection.Close();
    }
}

不幸的是,异常不是确定性的 - 我已经看到它发生在从第4个命令执行到具有相同代码的同一文件的第6149个的任何地方。它总是出现在command.ExecuteScalar()行上。如果此代码中存在资源泄漏,请帮我找到。

我已尝试安装在http://support.microsoft.com/kb/2760394找到的修补程序(并进行了所需的注册表更改),但它无法解决问题。任何建议都会受到赞赏和积极追求。

这是在Windows 7,C#4.0(控制台和WinForms),4 GB RAM

上运行

1 个答案:

答案 0 :(得分:2)

我会尝试一些事情:

  1. 由于数据库的用户只是应用程序,我会以独占模式打开数据库,这将有助于驱动程序摆脱管理锁定文件的开销(并且还应加快对数据库的访问)。
  2. // Share Mode=12 - exclusive mode (16 for multi-user)
    string constr = @"Provider=Microsoft.ACE.OLEDB.12.0;" +
                     "Mode=12;Data Source = C:\datafile.res;user id=;password=;";
    
    1. 程序启动时打开与Access数据库的连接,并在应用程序关闭之前保持打开状态 在紧密循环中,锁定文件问题会逐渐增加并导致各种难以调试的奇怪问题 只需在Access数据库中创建一个包含单个记录的虚拟表,然后打开该表以读取记录,但保留对该连接的永久引用:
    2. private OleDbCommand PermanentCommand;
      
      void KeepLinkOpen() {
         if (PermanentCommand == null || 
             PermanentCommand.Connection == null || 
             PermanentCommand.Connection.State == System.Data.ConnectionState.Closed) {
      
           OleDbConnection conn = new OleDbConnection(connectionString);
           conn.Open();
           PermanentCommand = new OleDbCommand("SELECT * FROM DummyTable", conn);
           PermanentCommand.ExecuteReader(System.Data.CommandBehavior.Default);
        }    
      }
      
      void Disconnect() {
        if (PermanentCommand != null) {
            if (PermanentCommand.Connection != null) {
                PermanentCommand.Connection.Close();
            }
            PermanentCommand.Dispose();
            PermanentCommand = null;
        }
      }