Question

I am having problems with SQL Server dropping a connection after I have dropped and re-created a given database and the next time I try to execute a command against a new connection on that same database, I get:

A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)

Here is the TCP version (If I try connecting to another server)

A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)

Here are the steps to repro the problem:

  1. Open a connection to a database and execute a sql command
  2. Drop the database
  3. Re-Create the database
  4. Open a new connection to the same database and attempt to run a command against it

Result: I receive an exception

Here is the Code:

using (var conn = new System.Data.SqlClient.SqlConnection("Data Source=.;Initial Catalog=DBNAME;Integrated Security=True"))
{
    conn.Open();
    var cmd = conn.CreateCommand();
    cmd.CommandText = "UPDATE ...";
    cmd.ExecuteNonQuery();
}

string sql = "Alter Database DBNAME set single_user with rollback immediate drop database DBNAME";
var server = new Microsoft.SqlServer.Management.Smo.Server(".");
server.ConnectionContext.ExecuteNonQuery(sql);
server.ConnectionContext.Disconnect();

sql = File.ReadAllText("PathToDotSqlFile..."));
server = new Microsoft.SqlServer.Management.Smo.Server(".");
server.ConnectionContext.ExecuteNonQuery(sql);
server.ConnectionContext.Disconnect();

using (var conn = new System.Data.SqlClient.SqlConnection("Data Source=.;Initial Catalog=WER_CONFIG;Integrated Security=True"))
{
    conn.Open();
    var cmd = conn.CreateCommand();
    cmd.CommandText = "UPDATE ...";
    cmd.ExecuteNonQuery();
}

The error occurs on the line 'cmd.ExecuteNonQuery()' at the very end. It appears that even though I am creating a new connection each time I connect, sql server is keeping track of something (or possibly the ADO.net code) where the next time I ask for a connection, it gives me one that is already used or has been closed on the server side. It doesn't realize it was closed by the server (presumably because of the database it is connected to being dropped) until you try to execute another command against it.

Note that if I don't do the first step of executing the initial query, and I just drop the database, re-create it, and execute a command, I do not receive this error. I think establishing that initial connection before the database is dropped is an important part of this error.

I have also tried using an external process to drop and recreate the database like so:

ProcessStartInfo info = new ProcessStartInfo("sqlcmd.exe", " -e -E -S . -Q \"Alter Database DBNAME set single_user with rollback immediate drop database DBNAME\"");
var p = Process.Start(info);
p.WaitForExit();

info = new ProcessStartInfo("sqlcmd.exe", " -i " + PathToDotSqlFile);
p = Process.Start(info);
p.WaitForExit();

And that did not help.

Is there a way to create a new SqlConnection and ensure it is clean and not from a pool? Any other suggestions on how to solve this problem?

UPDATE: Using SqlConnection.ClearPool() did solve the problem but I chose to just edit my connection string with pooling=false which also worked.

Was it helpful?

Solution

ADO.NET automatically manages a connection pool. When you "close" a connection in your application, it is returned to the pool and kept alive, in case you request a connection with the same connection string. This could be the reason why your "new" connection is stale.

You could try to turn off this behaviour by adding pooling=false as parameter to your connection string.

OTHER TIPS

Don't know about SQL2008, but this sounds like a connection pooling problem on the application side. In the old days, we added "OLEDB Services=-1" to the connection string to turn off connection pooling. There is probably a more elegant way to do this now.

edit: ADO.Net 2.0 seems to have added a ClearPool function to the SQLConnection object. (http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearpool(VS.80).aspx) I am very interested to know if this works.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top