0

I'm running a multithreaded application that connects to a database, the connections are closed when I'm done with them (and I dispose of all the threads). I've tried clearing the connection pools, setting pooling=false and I've used both .dispose and .close.

I get the error "cannot drop the database X because it is currently in use" if I try to drop the database I connected to after the connections have all been closed. Below is my code:

Dim comExecuteInsert As New SqlCommand
Dim comm As New SqlConnection
If (Not comm Is Nothing) Then
    comm = Nothing
End If
comExecuteInsert.Connection = comm
comExecuteInsert.CommandType = CommandType.StoredProcedure
comExecuteInsert.CommandText = strProcedureName
comExecuteInsert.CommandTimeout = 26000
comExecuteInsert.Parameters.Add("@tableName", SqlDbType.VarChar, 100).Value = strTableName
comExecuteInsert.Parameters.Add("@filename", SqlDbType.VarChar, 500).Value = strFileName
comExecuteInsert.ExecuteScalar()
comExecuteInsert.Parameters.Clear()

comExecuteInsert = Nothing
comm.Close()
SqlConnection.ClearPool(comm)

The stored procedure creates temporary tables which it later drops and inserts data into tables existing in the database.

RobinReborn
  • 431
  • 2
  • 7
  • 23

5 Answers5

2

If you are trying to close any connection to a db so you can drop it, you can do execute something like the following against the master database in Management Studio:

Alter Database MyDatabaseName Set Single_User With Rollback Immediate
GO
Drop Database MyDatabaseName
GO

To do this in code, you would need to open a separate connection to the master database and execute each of the above statements individually (and not try to execute the GO words). Keep in mind that this will kill all connection to the database including ones other than your own no matter what they might be doing.

Thomas
  • 63,911
  • 12
  • 95
  • 141
2

You are not disposing your command object.

Instead of

comExecuteInsert = Nothing

try

comExecuteInsert.Dispose

Or try the following:

Using comm As New SqlConnection
  Using comExecuteInsert As New SqlCommand
    comExecuteInsert.Connection = comm
    comExecuteInsert.CommandType = CommandType.StoredProcedure
    comExecuteInsert.CommandText = strProcedureName
    comExecuteInsert.CommandTimeout = 26000
    comExecuteInsert.Parameters.Add("@tableName", SqlDbType.VarChar, 100).Value = strTableName
    comExecuteInsert.Parameters.Add("@filename", SqlDbType.VarChar, 500).Value = strFileName
    comExecuteInsert.ExecuteScalar()
    comExecuteInsert.Parameters.Clear()
    comm.Close()
  End Using
End Using
SSS
  • 4,807
  • 1
  • 23
  • 44
2

I missed the bit where you said you were dropping a database. You need to use

SqlConnection.ClearAllPools()

SQL Server caches connections for re-use. The above clears the cached connections.

For example...

Sub Demo_DropDatabase(ByVal strCnn As String, ByVal strDBName As String)
  Using cnnSQLS As New SqlConnection(strCnn)
    SqlConnection.ClearAllPools()
    cnnSQLS.Open()
    Dim strSQL As String = "DROP DATABASE [" & strDBName & "]"
    Using cmdDrop As New SqlCommand(strSQL, cnnSQLS)
      cmdDrop.ExecuteNonQuery() 'N.B. may throw exception '
    End Using
    cnnSQLS.Close()
  End Using
End Sub
SSS
  • 4,807
  • 1
  • 23
  • 44
1

use the using keyword, see Does End Using close an open SQL Connection

Community
  • 1
  • 1
Ivo
  • 3,406
  • 4
  • 33
  • 56
  • I've tried that and it doesn't work, perhaps there's something in my stored procedure that is keeping my database open. – RobinReborn May 16 '11 at 18:58
0

Use below T-SQL in your VB.Net Code to remove existing connections.

TSQL

declare @vSqlTx AS varchar(max);

select @vSqlTx = concat(@vSqlTx, ' KILL ', spid, ';', CHAR(13))
from sys.sysprocesses
where DB_NAME(NULLIF(dbid, 0))  = <'yourDatabaseName'>
and spid != @@spid;

print @vSqlTx;
exec (@vSqlTx);

VB.NET Code:

Private Sub CloseAllOtherConnections(ByVal conStr As String, ByVal databaseName As String)
    Dim strSqlText As String 

    Using con As New SqlConnection(conStr)      
        SqlConnection.ClearAllPools()
        con.Open()


        strSqlText = "  declare @vSqlTx AS varchar(max);

                    select @vSqlTx = concat(@vSqlTx, ' KILL ', spid, ';', CHAR(13))
                    from sys.sysprocesses
                    where DB_NAME(NULLIF(dbid, 0))  = '" & databaseName & "'
                    and spid != @@spid;

                    print @vSqlTx;
                    exec (@vSqlTx); "

        Dim cmd As New SqlCommand(strSqlText, con)
        cmd.ExecuteNonQuery()       
        con.Close()     
  End Using

End Sub
Bhavesh Harsora
  • 655
  • 5
  • 14