如何查找和关闭winforms中任何打开的OleDbConnections?

时间:2016-11-16 16:17:08

标签: c# winforms ms-access oledbconnection

首先:我在这个主题上看过很多堆栈讨论(以及其他论坛)。 这不是重复。我尝试了许多建议但无济于事。

我有一个庞大而复杂的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中的某些东西知道连接并知道如何释放它 - 那么如何在不退出应用程序的情况下使用相同的逻辑呢?

有什么想法吗?

3 个答案:

答案 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很可能没有释放与数据库的连接。请确保你:

  • 明确调用“关闭”ADOX连接对象
  • 调用'Dispose'他们
  • 调用System.Runtime.InteropServices.Marshal.FinalReleaseComObject(db.ActiveConnection);
  • 调用System.Runtime.InteropServices.Marshal.Marshal.FinalReleaseComObject(db);
  • 将它们设置为Nothing / null

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