Domanda

Sto riscontrando problemi con la caduta di una connessione da parte di SQL Server dopo che ho lasciato cadere e ricreato un determinato database e la prossima volta che provo ad eseguire un comando su una nuova connessione su quello stesso database, ottengo:

  

Si è verificato un errore a livello di trasporto durante l'invio della richiesta al server. (provider: provider di memoria condivisa, errore: 0 - nessun processo si trova sull'altra estremità della pipe.)

Ecco la versione TCP (se provo a collegarmi a un altro server)

  

Si è verificato un errore a livello di trasporto durante l'invio della richiesta al server. (provider: provider TCP, errore: 0 - una connessione esistente è stata forzatamente chiusa dall'host remoto.)

Ecco i passaggi per ripetere il problema:

  1. Apri una connessione a un database ed esegui un comando sql
  2. Rilascia il database
  3. Ricrea il database
  4. Apri una nuova connessione allo stesso database e prova a eseguire un comando contro di esso

Risultato: ricevo un'eccezione

Ecco il codice:

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

L'errore si verifica sulla riga 'cmd.ExecuteNonQuery ()' alla fine. Sembra che anche se sto creando una nuova connessione ogni volta che mi connetto, il server sql tiene traccia di qualcosa (o forse del codice ADO.net) in cui la prossima volta che chiedo una connessione, me ne dà una già utilizzata o è stato chiuso sul lato server. Non si rende conto che è stato chiuso dal server (presumibilmente a causa del database a cui è stato eliminato) finché non si tenta di eseguire un altro comando contro di esso.

Notare che se non eseguo il primo passaggio dell'esecuzione della query iniziale, e trascino semplicemente il database, lo ricreamo ed eseguo un comando, non ricevo questo errore. Penso che stabilire quella connessione iniziale prima che il database venga eliminato sia una parte importante di questo errore.

Ho anche provato a utilizzare un processo esterno per eliminare e ricreare il database in questo modo:

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 questo non ha aiutato.

C'è un modo per creare un nuovo SqlConnection e assicurarsi che sia pulito e non da un pool? Altri suggerimenti su come risolvere questo problema?

AGGIORNAMENTO: L'utilizzo di SqlConnection.ClearPool () ha risolto il problema ma ho scelto di modificare la mia stringa di connessione con pooling = false che ha funzionato.

È stato utile?

Soluzione

ADO.NET gestisce automaticamente un pool di connessioni. Quando " chiudi " una connessione nell'applicazione, viene restituita al pool e mantenuta attiva, nel caso in cui si richieda una connessione con la stessa stringa di connessione. Questo potrebbe essere il motivo per cui il tuo "nuovo" la connessione è obsoleta.

Puoi provare a disattivare questo comportamento aggiungendo pooling = false come parametro alla tua stringa di connessione.

Altri suggerimenti

Non so di SQL2008, ma sembra un problema di pool di connessioni sul lato dell'applicazione. Ai vecchi tempi, abbiamo aggiunto "OLEDB Services = -1" alla stringa di connessione per disattivare il pool di connessioni. C'è probabilmente un modo più elegante per farlo ora.

modifica: ADO.Net 2.0 sembra aver aggiunto una funzione ClearPool all'oggetto SQLConnection. ( http: // msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearpool(VS.80).aspx ) Sono molto interessato a sapere se funziona.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top