首先:我在这个主题上看过很多堆栈讨论(以及其他论坛)。 这不是重复。我尝试了许多建议但无济于事。
我有一个庞大而复杂的c#winforms应用程序。由于各种原因,它会在不同时间将OleDB连接到Access数据库。在某个函数中,我们需要MOVE(复制+删除)mdb文件,但由于它已被锁定,因此无法完成。我已经尝试了许多不同的东西来解锁/释放mdb文件,有时它可以工作。但在某种100%可重现的情况下,它无法解锁。我们有2个全局oledb连接变量,我们在任何地方重复使用,以提高效率,并避免在任何地方都使用1-off连接。当我们想要关闭连接时,这两个连接变量很有用,所以我们可以删除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();
}
}
我将真实传递给上述功能。
小恩惠:请不要浪费时间说Access是坏的,不可扩展的等等。我知道它很糟糕且不可扩展,但这是遗留的要求,我们现在仍然坚持使用它。感谢。
另一个想法:当然我的winforms应用程序知道所有开放的oledbconnections。有没有办法告诉c#查找并迭代所有打开的连接?当我关闭/退出我的应用程序时 - poof - 释放了与mdb的开放连接,我可以删除该文件。所以.net中的某些东西知道连接并知道如何释放它 - 那么如何在不退出应用程序的情况下使用相同的逻辑呢?
有什么想法吗?
答案 0 :(得分:2)
处理过的IDataReaders?
您是否正确禁用了所有IDataReader对象?它们可能会阻止连接正常关闭。
跟踪解决方案
无论如何,您至少需要更好地跟踪所有连接。这听起来像是一个非常大的项目。您需要绝对确保所有连接都已被处置。
<强> 1。新的TrackedOleDbConnection对象
创建一个继承自OleDbConnection的TrackedOleDbConnection对象,但添加一个名为StillOpen的静态ConcurrentList。构建TrackedOleDbConnection时,添加到列表中,当它被处置(覆盖该功能)时,将其删除。
public class TrackedOleDbConnection: OleDbConnection
{
public TrackedOleDbConnection() : base()
{
}
public TrackedOleDbConnection(string ConnectionString) : base(ConnectionString)
{
}
//You don't need to create a constructor for every overload of the baseclass, only for overloads your project uses
ConcurrentList<TrackedOleDbConnection> ActiveConnections = new ConcurrentList<TrackedOleDbConnection>();
void AddActiveConnection()
{
ActiveConnections.Add(this);
}
override void Dispose()
{
ActiveConnections.RemoveIfExists(this); //Pseudo-function
GC.SuppressFinalise(this);
}
//Destructor, to ensure the ActiveConnection is always removed, if Dispose wasn't called
~TrackedOleDbConnection()
{
//TODO: You should log when this function runs, so you know you still have missing Dispose calls in your code, and then find and add them.
Dispose();
}
}
<强> 2。不要再直接引用OleDbConnection
然后在您的解决方案中进行简单的查找和替换,以使用TrackedOleDbConnection。
最后,在您的CloseOleDBConnections函数中,您可以访问TrackedOleDbConnection.StillOpen,看看您是否在某处遇到了未跟踪连接的问题。
如果您发现此类未解决的问题,请不要使用单个中央引用,而应使用using
以确保正确处理您的连接。
答案 1 :(得分:0)
可能你唯一需要的就是复制文件可能不需要弄乱连接。请看一下:
https://www.raymond.cc/blog/copy-locked-file-in-use-with-hobocopy/
答案 2 :(得分:0)
ADOX很可能没有释放与数据库的连接。请确保你:
当某个文件句柄调用close时,close请求被放入队列中以供内核处理。换句话说,即使关闭一个简单的文件也不会立即发生。为此,您可能必须放入一个时间框的循环来检查.LDB文件是否被删除......尽管这最终需要用户等待。寻求这种方法的任何其他替代方案,尽管过去需要使用其他格式/连接IME。