Pergunta

Estou tendo problemas com SQL Server soltando uma conexão depois de eu ter deixado cair e re-criou um banco de dados e da próxima vez que tentar executar um comando contra uma nova ligação no mesmo banco de dados, eu recebo:

Um erro de nível de transporte ocorreu ao enviar o pedido para o servidor. (Provider: Shared provedor de memória, erro:. 0 - Nenhum processo está na outra extremidade do tubo)

Aqui é a versão TCP (Se eu tentar conectar a outro servidor)

Um erro de nível de transporte ocorreu ao enviar o pedido para o servidor. (Provedor: TCP Provider, erro:. 0 - uma conexão existente forçosamente foi fechada pelo host remoto)

Aqui estão os passos para Repro o problema:

  1. Abrir uma conexão com um banco de dados e executar um comando SQL
  2. Drop the banco de dados
  3. recriar o banco de dados
  4. Abra uma nova ligação para o mesmo banco de dados e tentativa de executar um comando contra ele

Resultado: Eu recebo uma exceção

Aqui está o código:

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();
}

O erro ocorre na linha 'cmd.ExecuteNonQuery ()' no final. Parece que mesmo que eu estou criando uma nova conexão cada vez que ligar, sql server é manter o controle de algo (ou possivelmente o código ADO.net), onde na próxima vez que pedir uma ligação, dá-me um que já é usado ou foi fechada no lado do servidor. Ele não percebe que foi fechada pelo servidor (presumivelmente por causa do banco de dados que está ligado ao ser descartado) até que você tentar executar um outro comando contra ela.

Note que, se eu não fizer o primeiro passo da execução da consulta inicial, e eu apenas deixar cair o banco de dados, re-criá-lo, e executar um comando, eu não receber esse erro. Eu acho que estabelecer essa conexão inicial, antes de o banco de dados é descartado é uma parte importante deste erro.

Eu também tentei usando um processo externo para eliminar e recriar o banco de dados da seguinte forma:

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();

E isso não ajuda.

Existe uma maneira de criar um novo SqlConnection e garantir que ele está limpo e não a partir de uma piscina? Quaisquer outras sugestões sobre como resolver este problema?

UPDATE: Usando SqlConnection.ClearPool () conseguiu resolver o problema, mas eu escolhi para apenas editar a minha string de conexão com pooling = false que também trabalhou

.
Foi útil?

Solução

ADO.NET gerencia automaticamente um pool de conexão. Quando você "fechar" uma conexão em seu aplicativo, ele é retornado para a piscina e mantida viva, no caso de você solicitar uma conexão com a mesma seqüência de conexão. Esta poderia ser a razão pela qual a sua ligação "novo" é obsoleto.

Você poderia tentar desativar esse comportamento adicionando pooling=false como parâmetro para a cadeia de ligação.

Outras dicas

Não sei sobre SQL2008, mas isso soa como um pool de conexão problema no lado do aplicativo. Nos velhos tempos, nós adicionamos "OLEDB Serviços = -1" para a seqüência de conexão para desligar o pool de conexão. Há provavelmente uma maneira mais elegante de fazer isso agora.

edit: ADO.Net 2.0 parece ter acrescentado uma função ClearPool ao objeto SQLConnection. ( http: // msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearpool(VS.80).aspx ) estou muito interessado em saber se isso funciona.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top