为什么Oledb Connection.Close()需要太长时间才能执行?

时间:2019-04-26 15:05:10

标签: c# winforms ms-access oledb

在开发用于连接到本地数据库的桌面应用程序的过程中,我将数据库移动到了网络位置,现在每次调用Connection.Close()时,程序都会挂起5-15秒。当数据库存储在本地计算机上时,我很少会看到此问题,但是现在它在网络上,几乎每次我尝试使用Close()时,它都会挂起。我对数据库进行的第一个调用甚至都不查询它,它只是我为了确保用户可以连接而打开和关闭的测试连接,但是它仍然挂得太久了。

我以前曾问过这个问题,但是除了“尝试使用using(){}清理c#之外”,没有人能提供建议或解决方案。这不会以任何方式影响Close()时间。

连接字符串中是否有一个选项可以解决此问题?有人知道为什么会这样吗?

我使用的连接字符串是:

CONNECTION_STRING = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=\\NEWTORK\Shared\Database\Database.accdb; Persist Security Info=False;"

private void

  Form_Login_Load(object sender, EventArgs e)
  {
    OleDbConnection Connection = new OleDbConnection();
    Connection.ConnectionString = CONNECTION_STRING;
    try
    {
      Console.Write("Connection Opening.....");
      Connection.Open();
      Console.WriteLine("Connection Opened");
      Console.Write("Writing Status Text.....");
      lbl_Status.Text = "Online";
      Console.WriteLine("Written Status Text");
      Console.Write("Connection Closing.....");
      Connection.Close();
      Console.WriteLine("Connection Closed");
    }
    catch (Exception Ex)
    {
      lbl_Status.Text = "Offline";
      lbl_Status.ForeColor = System.Drawing.Color.FromArgb(255, 0, 0);
      MessageBox.Show("Could not connect to Database");
    }
  }

在输出窗口中,我立即看到打开消息和书写状态消息,但是该应用程序挂在'Console.Write(“ Connection Closing .....”);“之前。线。 5-15秒后,关闭消息将出现在窗口中。

应用程序中有许多连接确实会查询数据库,并且似乎在尝试关闭所有连接之前也会挂起。我似乎确实注意到,在不关闭应用程序的情况下重复相同的查询有时会导致重复关闭的关闭时间更快,但是在任何查询的第一次尝试中,它总是挂起。

4 个答案:

答案 0 :(得分:1)

最终为我工作的是: 当Connection.Close()方法的滞后时间很长时,我使用的是Microsoft Access数据库引擎2016(x64)。由于不相关的原因,我需要卸载2016引擎并使用2010(x86)版本。现在,我的Connection.Close()时间平均约为40毫秒,这对于我的应用程序而言完全可以接受。

答案 1 :(得分:0)

如果数据库与程序之间有任何待处理的事务,则Close()将回滚它们。它还必须从连接池中请求并删除它,这在远程驱动器上可能需要更长的时间。这可能是您的问题吗?

Here are the docs on the method.

要解决此问题,您可以使用BackgroundWorker来执行它,如下所示:

var b = new BackgroundWorker();
b.DoWork += CloseDB;
b.RunWorkerCompleted += someMethodAfterClose;
b.RunWorkerAsync();

CloseDB:

public void CloseDB(object sender, DoWorkEventArgs e) {
    someConnection.Close();
}

答案 2 :(得分:0)

通常这可以是服务器设置。如果防火墙+ Windows Defender处于活动状态,则它将扫描所有“文件”访问-结果打开非常缓慢,当然还有close()。

尝试在防火墙和Windows Defender关闭的情况下运行共享文件夹所在的计算机。我看到这通常可以解决较大的延迟。当然,使用基于套接字的技术可以消除此问题(例如:基于服务器)。但是,您拥有的东西,通常不是您的代码速度,而是“ Windows文件”系统以及网络和防病毒软件的系统速度是造成此速度下降的原因。

答案 3 :(得分:0)

这可能会被标记为“不是答案”,但是我也有这个问题,而且似乎没有人找到真正的解释,因此,我提出了一些症状,而不是提出一个多余的问题:

  • 当办公室更新到Windows 10(从Windows 7)时,开始发生的频率更高。
  • 经常发生,但并非总是如此。有时OleDb连接关闭/处置非常快,有时会挂起〜10-15 s。对于任何给定的连接尝试,无论何时使用相同的Access数据库,相同的计算机和相同的进程,这种变化似乎都是随机的。
  • 本地和网络上的数据库都可能发生挂起,尽管尚未测试过是否一个数据库比另一个数据库更频繁。
  • 即使连接不做任何更改或事务(即仅执行SELECT查询),也会发生。
  • 仅在OleDb连接上发生,即用户通过Access接口打开和关闭数据库就可以了。

更新

无奈之下,我尝试过在后台线程中关闭连接的建议,以避免在此过程中占用主线程。但是当我这样做时,以后每次启动后续连接时,都会出现此错误:

未处理的异常:System.AccessViolationException:尝试读取或写入受保护的内存。这通常表明其他内存已损坏

谷歌搜索表明,在处理Access数据库连接时,这似乎发生在许多人身上,但通常是出于未知的原因。

因此,我尝试了另一种建议,将conn字符串更改为包含OLE DB Services=-1;。起初,这似乎可以解决问题。据我所知,没有专家可以通过将一些连接资源留在幕后开放以供重用,即使在处置conn对象之后,也基本上避免了挂起问题。对我很好...除非最终似乎关闭了这些资源(可能是超时),然后稍后建立连接,回到上面莫名其妙的AccessViolationException

潜在的解决方案

通过将各种Web评论和我自己的实验结合在一起:

  • OleDb在多线程中表现不佳。
  • 关闭应用程序中的 last 开放访问连接,无论是什么数据库,似乎都会触发OleDb库本身内部的某些资源的卸载,因此这可能是一项耗时的操作。 / li>

所以我做了什么,在我的应用程序内部添加了一个空的Access数据库,并在启动时打开了一个OleDb连接。我不处理连接,也不维护对连接的引用,以防止其自行关闭。这样,对后续连接的任何处置都不会触发OleDb所保留的任何资源的卸载。

这是一个hack,但是到目前为止,这似乎可以解决原始问题。

当然,真实的答案是避免使用Access数据库!