为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
撒科打诨 2022-12-31 13:42:03
在开发连接到本地数据库的桌面应用程序期间,我将数据库移动到网络位置,现在每次调用 Connection.Close() 时程序都会挂起 5-15 秒。当数据库存储在本地计算机上时,我很少会看到这个问题,但现在它在网络上,几乎每次我尝试 Close() 时它都会挂起。我对数据库的第一次调用我什至没有查询它,它只是一个测试连接,我打开和关闭以确保用户可以连接,但它仍然挂起太久。我以前见过这个问题,但是除了“尝试使用(){}让 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(“连接关闭......”)之前挂起;' 线。5-15 秒后,关闭消息出现在窗口中。应用程序中有许多连接查询数据库,它似乎在尝试关闭所有连接之前挂起。我似乎确实注意到,在不关闭应用程序的情况下重复相同的查询有时会导致重复关闭的关闭时间更快,但它总是在第一次尝试任何查询时挂起。
查看完整描述

4 回答

?
翻阅古今

TA贡献1780条经验 获得超5个赞

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



查看完整回答
反对 回复 2022-12-31
?
墨色风雨

TA贡献1853条经验 获得超6个赞

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

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


查看完整回答
反对 回复 2022-12-31
?
缥缈止盈

TA贡献2041条经验 获得超4个赞

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

这是有关该方法的文档。

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

var b = new BackgroundWorker();

b.DoWork += CloseDB;

b.RunWorkerCompleted += someMethodAfterClose;

b.RunWorkerAsync();

关闭数据库:


public void CloseDB(object sender, DoWorkEventArgs e) {

    someConnection.Close();

}


查看完整回答
反对 回复 2022-12-31
?
噜噜哒

TA贡献1784条经验 获得超7个赞

这可能会被标记为“不是答案”,但我也有这个问题,而且似乎没有人找到真正的解释,所以与其创建一个多余的问题,不如以下是我的一些症状:

  • 当办公室更新到 Windows 10(从 Windows 7)时开始更频繁地发生。

  • 经常发生但并非总是如此。有时 OleDb 连接关闭/处理非常快,有时它会挂起 ~10-15 秒。对于任何给定的连接尝试,任何时候的变化似乎都是随机的,即使使用相同的 Access 数据库、相同的机器和相同的进程也是如此。

  • 位于本地和网络上的数据库都可能发生挂起,但尚未测试一个是否比另一个更频繁。

  • 即使连接没有进行任何更改或事务(即只是 SELECT 查询)也会发生。

  • 只发生在 OleDb 连接上,即用户通过 Access 接口打开和关闭数据库是可以的。

更新

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

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

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

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

潜在的解决方案

通过拼凑各种网络评论和我自己的实验:

  • OleDb 不能很好地处理多线程。

  • 关闭应用程序中最后打开的 Access 连接,无论是什么数据库,似乎都会触发 OleDb 库本身内部某些资源的卸载,因此这是一个潜在的耗时操作。

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

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

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


查看完整回答
反对 回复 2022-12-31
  • 4 回答
  • 0 关注
  • 221 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信