我在使用 VB 编写的、在三个 IIS 服务器上运行的 ASP.NET 应用程序时遇到数据库连接错误。底层数据库是 MS Access,它位于共享网络设备上。它使用实体框架、代码优先实现和 JetEntityFrameworkProvider。
应用程序运行稳定。但是,打开数据库连接的 1000 次尝试中大约有 1 次失败,出现以下两个错误之一:
06:33:50 DbContext "Failed to open connection at 2/12/2020 6:33:50 AM +00:00 with error:
Cannot open database ''. It may not be a database that your application recognizes, or the file may be corrupt.
或者
14:04:39 DbContext "Failed to open connection at 2/13/2020 2:04:39 PM +00:00 with error:
Could not use ''; file already in use.
一秒钟后,通过刷新 (F5),错误消失并再次起作用。
有关环境和使用代码的详细信息。
连接字符串
<add name="DbContext" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=x:\thedatabase.mdb;Jet OLEDB:Database Password=xx;OLE DB Services=-4;" providerName="JetEntityFrameworkProvider" />
数据库上下文管理
应用程序使用公共属性来访问 DbContext。DbContext 在请求的生命周期内保存在 HttpContext.Current.Items 集合中,并在请求结束时被释放。
Public Shared ReadOnly Property Instance() As DbContext
Get
SyncLock obj
If Not HttpContext.Current.Items.Contains("DbContext") Then
HttpContext.Current.Items.Item("DbContext") = New DbContext()
End If
Return HttpContext.Current.Items.Item("DbContext")
End SyncLock
End Get
End Property
BasePage 初始化并释放 DbContext。
Protected Overrides Sub OnInit(e As EventArgs)
MyBase.OnInit(e)
DbContext = Data.DbContext.Instance
...
End Sub
Protected Overrides Sub OnUnload(e As EventArgs)
MyBase.OnUnload(e)
If DbContext IsNot Nothing Then DbContext.Dispose()
End Sub
我试过的
解决上述错误消息的许多关于 SO 的问题通常涉及无法建立与数据库的连接——它们根本无法连接。这与本案不同。连接在 99.99% 的时间内都有效。
除此之外,我还检查了:
- 权限:对 .mdb(数据库)和 .ldb(锁定文件)所在的共享授予完全访问权限。
- 网络连接:共享设备没有连接问题;这是一个千兆 LAN 连接
- 未达到最大并发连接数 255
- 未超过数据库的最大大小(db 只有 5 MB)
- 按照MS Dev-Net 帖子中的建议,将编译选项从“Any CPU”更改为“x86”
Quote: 我得到相同的“无法打开数据库''”错误,但完全随机(似乎)。MDB 文件小于 1Mb,因此对于 2Gb 限制没有问题,因为这个错误经常提到。它在 32 位版本的 Windows 上工作 100%,但我发现问题出在 64 位安装上。该应用程序被编译为“任何 CPU”。我将编译选项从“Any CPU”更改为“x86”,问题就消失了。
到目前为止没有任何帮助。
为了收集更多信息,我将一个 Nlog 记录器附加到 DbContext,它将所有数据库操作和查询写入日志文件。
Shared Log As Logger = LogManager.GetLogger("DbContext")
Me.Database.Log = Sub(s) Log.Debug(s)
调查日志我发现当上述错误之一发生在一台服务器上时,另一台服务器(总共 3 台)同时关闭了数据库连接。这里有两个对应于上述错误的例子:
06:33:50 DbContext "Closed connection at 2/12/2020 6:33:50 AM +00:00
14:04:39 DbContext "Closed connection at 2/13/2020 2:04:39 PM +00:00
假设
当 DbContext 的所有连接都已关闭时,相应的记录将从 .ldb 锁定文件中删除。当打开与数据库的连接时,将在锁定文件中添加一条记录。当这两个事件同时发生时,来自两个不同的服务器,对 .ldb 锁定文件存在写入冲突,从而导致出现上述错误。
问题
任何人都可以确认或证明这是错误的吗?有没有人经历过这种行为?也许我错过了其他东西。感谢您对此的意见和经验。
如果我的假设是真的,一个解决方案可能是使用一个帮助类来访问 db,它会捕获并处理这个错误,等待最短的时间段并再次尝试。
但这感觉有点不对劲。因此,我也愿意接受有关“适当”解决方案的建议。
编辑: “正确”的解决方案将使用 DBMS 服务器(如下面的评论中所述)。我知道这一点。现在,我不得不处理这个设计错误,而不是对此负责。此外,我无法在短期内改变它。