C# 如何在winforms中查找和关闭任何打开的OLEDB连接?

C# 如何在winforms中查找和关闭任何打开的OLEDB连接?,c#,winforms,ms-access,oledbconnection,C#,Winforms,Ms Access,Oledbconnection,第一:我已经看过很多关于这个主题的堆栈讨论(以及在其他论坛上)它不是重复的。我尝试了许多建议,但都无济于事 我有一个大型而复杂的c#winforms应用程序。由于各种原因,它会在不同时间与Access数据库建立OleDB连接。在某个函数中,我们需要移动(复制+删除)mdb文件,但无法执行,因为它已锁定。我已经尝试了很多不同的方法来解锁/释放mdb文件,有时它会起作用。但在某个100%可复制的场景中,它无法解锁。我们有两个全局oledb连接变量,我们在任何地方都重用,以提高效率,并避免在任何地方都

第一:我已经看过很多关于这个主题的堆栈讨论(以及在其他论坛上)它不是重复的。我尝试了许多建议,但都无济于事

我有一个大型而复杂的c#winforms应用程序。由于各种原因,它会在不同时间与Access数据库建立OleDB连接。在某个函数中,我们需要移动(复制+删除)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应用程序知道所有开放的OLEDB连接。没有办法告诉c#查找并迭代所有打开的连接吗?当我关闭/退出我的应用程序-poof-打开的mdb连接被释放,我可以删除该文件。所以.net中的某些东西知道连接并知道如何释放它——那么我如何在不退出应用程序的情况下利用相同的逻辑呢


有什么想法吗?

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

跟踪解决方案

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

1。新的TrackeDeletedBConnection对象

创建从OleDbConnection继承的TrackeDeletedBConnection对象,但添加名为StillOpen的静态ConcurrentList。构造TrackeDeletedBConnection时,将其添加到列表中,释放后(覆盖该函数),将其删除

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();
    }
}
public类trackedledbconnection:OleDbConnection
{
public-trackedledbconnection():base()
{
}
public-trackedledbconnection(string-ConnectionString):基本(ConnectionString)
{
}
//您不需要为基类的每个重载创建构造函数,只需要为项目使用的重载创建构造函数
ConcurrentList ActiveConnections=新建ConcurrentList();
void AddActiveConnection()
{
ActiveConnections.Add(这个);
}
重写void Dispose()
{
ActiveConnections.removiefexists(this);//伪函数
GC.最终确定(本);
}
//析构函数,以确保在未调用Dispose时始终删除ActiveConnection
~trackedledbconnection()
{
//TODO:您应该在该函数运行时进行日志记录,以便知道代码中仍然缺少Dispose调用,然后查找并添加它们。
处置();
}
}
2。不再直接引用OLEDB连接

然后在整个解决方案中进行简单的查找和替换,以使用TrackedledBConnection

最后,在关闭OLEDBConnections函数期间,您可以访问TrackeDeletedBonnection.StillOpen,查看是否存在未跟踪连接的问题


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

已处理的IDataReaders?

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

跟踪解决方案

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

1。新的TrackeDeletedBConnection对象

创建从OleDbConnection继承的TrackeDeletedBConnection对象,但添加名为StillOpen的静态ConcurrentList。构造TrackeDeletedBConnection时,将其添加到列表中,释放后(覆盖该函数),将其删除

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();
    }
}
public类trackedledbconnection:OleDbConnection
{
public-trackedledbconnection():base()
{
}
public-trackedledbconnection(string-ConnectionString):基本(ConnectionString)
{
}
//您不需要为基类的每个重载创建构造函数,只需要为项目使用的重载创建构造函数
ConcurrentList ActiveConnections=新建ConcurrentList();
void AddActiveConnection()
{
ActiveConnections.Add(这个);
}
重写void Dispose()
{
ActiveConnections.removiefexists(this);//伪函数
GC.最终确定(本);
}
//析构函数,以确保在未调用Dispose时始终删除ActiveConnection
~trackedledbconnection()
{
//TODO:您应该在该函数运行时进行日志记录,以便知道代码中仍然缺少Dispose调用,然后查找并添加它们。
处置();
}
}
2。不再直接引用OLEDB连接

然后在整个解决方案中进行简单的查找和替换,以使用TrackedledBConnection

最后,在关闭OLEDBConnections函数期间,您可以访问TrackeDeletedBonnection.StillOpen,查看是否存在未跟踪连接的问题

无论您在何处发现此类未跟踪的问题,都不要使用单一中心引用,而是使用
来确保您的连接