如何在winforms中找到并关闭任何打开的OleDbConnections

本文关键字:任何打 OleDbConnections winforms | 更新日期: 2023-09-27 18:18:26

我有一个庞大而复杂的c# Winforms应用程序。由于各种原因,它在不同的时间使OleDB连接到Access数据库。在某个函数中,我们需要移动(复制+删除)mdb文件,但它不能做,因为它是锁定的。我已经尝试了很多不同的东西来解锁/释放mdb文件,有时它工作。

但是在某个100%可复制的场景中,它不能被解锁。我们有两个全局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();
    }
}

我将true传递给上面的函数。

另一个想法:当然我的Winforms应用程序知道所有打开的oledbconnections。没有办法告诉c#查找和迭代所有打开的连接吗?当我关闭/退出我的应用程序-噗-打开连接到mdb被释放,我可以删除该文件。因此,.net中的某些东西知道连接并知道如何释放它——那么我如何在不退出应用程序的情况下使用相同的逻辑呢?

<

发布脚本/h2>

(我知道Access很糟糕,不可扩展,等等——这是一个遗留需求,我们现在坚持使用它)。

我看过很多关于这个话题的堆栈讨论(以及其他论坛)。我已经尝试了许多建议,但都无济于事。

如何在winforms中找到并关闭任何打开的OleDbConnections

已处置的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。仍然打开,看看你是否在某个地方遇到了未跟踪连接的问题。

无论您在哪里发现此类未跟踪的问题,不要使用单个中心引用,而是使用using来确保您的连接被正确处理。

如果您唯一需要做的就是复制文件,那么可能没有必要弄乱连接。请看这个:

https://www.raymond.cc/blog/copy-locked-file-in-use-with-hobocopy/

很可能ADOX没有释放到数据库的连接。确保你:

  • 显式调用"关闭"ADOX连接对象
  • 调用'Dispose'它们
  • 调用System.Runtime.InteropServices.Marshal.FinalReleaseComObject (db.ActiveConnection);
  • 调用System.Runtime.InteropServices.Marshal.Marshal.FinalReleaseComObject (db);
  • 设置为none/null

同样,当某个文件句柄调用close时,关闭请求被放入一个队列中,由内核处理。换句话说,即使关闭一个简单的文件也不会立即发生。为此,您可能必须放入一个时间框循环来检查.LDB文件是否已被删除…尽管这最终需要用户等待。请寻找此方法的任何其他替代方法,尽管过去使用其他格式/连接IME是必要的。