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

niknxzdl  于 2022-11-17  发布在  其他
关注(0)|答案(3)|浏览(121)

我有一个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不好,不可扩展等-这是一个遗留要求,我们现在坚持使用它)。
我已经看到了无数关于这个主题的堆栈讨论(和其他论坛上)。我已经尝试了无数的建议都无济于事。

slsn1g29

slsn1g291#

已处置IDataReader?

是否正确禁用了所有IDataReader对象?它们可能会阻止连接正确关闭。

跟踪解决方案

在任何情况下,你至少需要更好地跟踪你所有的连接,这听起来像是一个非常大的项目,你需要绝对确定所有的连接都被处理掉了。

1.新建跟踪的OleDbConnection对象

创建一个继承自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来确保正确地处理连接。

jpfvwuh4

jpfvwuh42#

如果你只需要复制文件,那么就没有必要破坏连接了。请看下面的例子:
https://www.raymond.cc/blog/copy-locked-file-in-use-with-hobocopy/

5lhxktic

5lhxktic3#

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

  • 显式调用“Close”ADOX连接对象
  • 叫“处理”他们
  • 调用系统.运行时.互操作服务.封送.最终释放通信对象(db.ActiveConnection);
  • 调用系统.运行时.互操作服务.封送.封送.最终发布组件对象(db);
  • 将它们设置为Nothing/null

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

相关问题