Pregunta

Estoy teniendo problemas con el hecho de que SQL Server interrumpa una conexión después de haber eliminado y recreado una base de datos determinada y la próxima vez que intente ejecutar un comando contra una nueva conexión en esa misma base de datos, obtengo:

  

Se ha producido un error de nivel de transporte al enviar la solicitud al servidor. (proveedor: proveedor de memoria compartida, error: 0: no hay ningún proceso en el otro extremo de la canalización).

Aquí está la versión de TCP (si intento conectarme a otro servidor)

  

Se ha producido un error de nivel de transporte al enviar la solicitud al servidor. (proveedor: proveedor de TCP, error: 0 - El host remoto cerró a la fuerza una conexión existente).

Aquí están los pasos para reprozar el problema:

  1. Abra una conexión a una base de datos y ejecute un comando sql
  2. Eliminar la base de datos
  3. Volver a crear la base de datos
  4. Abra una nueva conexión a la misma base de datos e intente ejecutar un comando en su contra

Resultado: recibo una excepción

Aquí está el 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();
}

El error se produce en la línea 'cmd.ExecuteNonQuery ()' al final. Parece que aunque estoy creando una nueva conexión cada vez que me conecto, el servidor SQL está haciendo un seguimiento de algo (o posiblemente del código ADO.net), donde la próxima vez que solicite una conexión, me proporcione una que ya está en uso. o ha sido cerrado en el lado del servidor. No se da cuenta de que el servidor lo cerró (probablemente debido a la base de datos a la que está conectado), hasta que intente ejecutar otro comando en su contra.

Tenga en cuenta que si no hago el primer paso de la ejecución de la consulta inicial y simplemente suelto la base de datos, la vuelvo a crear y ejecuto un comando, no recibo este error. Creo que establecer esa conexión inicial antes de que se elimine la base de datos es una parte importante de este error.

También he intentado usar un proceso externo para eliminar y volver a crear la base de datos de esta 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();

Y eso no ayudó.

¿Hay alguna forma de crear una nueva SqlConnection y garantizar que esté limpio y no desde un grupo? ¿Alguna otra sugerencia sobre cómo resolver este problema?

ACTUALIZACIÓN: el uso de SqlConnection.ClearPool () resolvió el problema, pero elegí simplemente editar mi cadena de conexión con pooling = false, que también funcionó.

¿Fue útil?

Solución

ADO.NET administra automáticamente un grupo de conexiones. Cuando " cerrar " Una conexión en su aplicación, se devuelve al grupo y se mantiene activa, en caso de que solicite una conexión con la misma cadena de conexión. Esta podría ser la razón por la que su " nuevo " la conexión es obsoleta.

Puedes intentar desactivar este comportamiento agregando pooling = false como parámetro a tu cadena de conexión.

Otros consejos

No sé sobre SQL2008, pero esto suena como un problema de agrupación de conexiones en el lado de la aplicación. En los viejos tiempos, agregamos " Servicios OLEDB = -1 " a la cadena de conexión para desactivar la agrupación de conexiones. Probablemente haya una forma más elegante de hacerlo ahora.

editar: ADO.Net 2.0 parece haber agregado una función ClearPool al objeto SQLConnection. ( http: // msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearpool(VS.80).aspx ) Estoy muy interesado en saber si esto funciona.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top