我有一个C# Winforms应用程序,它很大很复杂。它会在不同的时间因为不同的原因建立与Access数据库的OleDB连接。在某个函数中,我们需要移动(复制+删除)mdb文件,但无法完成,因为它被锁定了。我尝试了很多不同的方法来解锁/释放mdb文件,有时它会起作用。
但是在一个100%可重复的场景中,它是不能被解锁的。我们有两个全局oledb连接变量,我们在任何地方都可以重用,为了提高效率,也为了避免在任何地方都有一个一次性的连接。这两个连接变量在我们想要关闭连接时很有用,所以我们可以删除mdb。
以下是我的函数(通常有效--只是在本例中无效),用于强制关闭/释放来自winforms应用程序的2个oledb连接:
public static void CloseOleDBConnections(bool forceReleaseAll = false) {
if ( DCGlobals.Connection1 != null )
DCGlobals.Connection1.Close();
if ( DCGlobals.Connection2 != null )
DCGlobals.Connection2.Close();
if ( forceReleaseAll ) {
DCGlobals.Connection1.Dispose();
DCGlobals.Connection2.Dispose();
OleDbConnection.ReleaseObjectPool();
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
}
}
我将true传递给上面的函数。
另一个念头:当然,我的Winforms应用程序知道所有打开的oledb连接。难道没有办法告诉c#找到并迭代所有打开的连接吗?当我关闭/退出我的应用程序时-噗-打开的mdb连接被释放,我可以删除文件。所以.net中的某些东西知道连接,并知道如何释放它--那么我如何在不退出应用程序的情况下进入相同的逻辑呢?
后脚本
(我知道Access不好,不可扩展等-这是一个遗留要求,我们现在坚持使用它)。
我已经看到了无数关于这个主题的堆栈讨论(和其他论坛上)。我已经尝试了无数的建议都无济于事。
3条答案
按热度按时间slsn1g291#
已处置IDataReader?
是否正确禁用了所有IDataReader对象?它们可能会阻止连接正确关闭。
跟踪解决方案
在任何情况下,你至少需要更好地跟踪你所有的连接,这听起来像是一个非常大的项目,你需要绝对确定所有的连接都被处理掉了。
1.新建跟踪的OleDbConnection对象
创建一个继承自OleDbConnection的TrackedOleDbConnection对象,但添加一个名为StillOpen的静态ConcurrentList。构造TrackedOleDbConnection时,将添加到列表中,在释放该对象(重写该函数)时,将其移除。
2.不再直接引用OleDbConnection
然后在解决方案中执行简单的查找和替换,以使用TrackedOleDbConnection。
最后,在执行CloseOleDBConnections函数时,可以访问TrackedOleDbConnection.StillOpen来查看是否有未跟踪连接的问题。
无论在何处发现此类未跟踪的问题,都不要使用单一的中心引用,而是使用
using
来确保正确地处理连接。jpfvwuh42#
如果你只需要复制文件,那么就没有必要破坏连接了。请看下面的例子:
https://www.raymond.cc/blog/copy-locked-file-in-use-with-hobocopy/
5lhxktic3#
ADOX很可能没有释放与数据库的连接。请确保:
同样,当某个文件句柄调用close时,关闭请求会被放入队列等待内核处理。换句话说,即使关闭一个简单的文件也不会立即发生。为此,你可能需要放入一个时间框循环来检查.LDB文件是否被删除......尽管这最终会要求用户等待。寻找其他替代方法,尽管在过去对于其他格式/连接IME是必要的。