¿Cómo se detiene una instancia de usuario de Sql Server? (Los files de database de instancias de usuario Express Sql están bloqueados, incluso después de detener el service Sql Express)

Cuando se utiliza la característica Instancia de usuario de SQL Server Express 2005 con una cadena de connection como esta:

<add name="Default" connectionString="Data Source=.\SQLExpress; AttachDbFilename=C:\My App\Data\MyApp.mdf; Initial Catalog=MyApp; User Instance=True; MultipleActiveResultSets=true; Trusted_Connection=Yes;" /> 

Nos encontramos con que no podemos copyr los files de la database MyApp.mdf y MyApp_Log.ldf (porque están bloqueados) incluso después de detener el service SqlExpress, y tenemos que recurrir a configurar el service SqlExpress desde el modo de inicio automático al manual, y luego reiniciando la máquina, antes de que podamos copyr los files.

Comprendí que detener el service SqlExpress también debería detener todas las instancias de usuario, lo que debería liberar los lockings en esos files. Pero este no parece ser el caso. ¿Podría alguien arrojar algo de luz sobre cómo detener una instancia de usuario, de modo que sus files de database ya no estén bloqueados?


Actualizar

De acuerdo, dejé de ser flojo y encendí Process Explorer. Lock fue retenido por sqlserver.exe, pero hay dos instancias de SQL Server:

 sqlserver.exe PID: 4680 User Name: DefaultAppPool sqlserver.exe PID: 4644 User Name: NETWORK SERVICE 

La instancia de sqlserver.exe abre el file con el PID: 4680

Detener el service "SQL Server (SQLEXPRESS)" eliminó el process con PID: 4644, pero dejó PID: 4680 solo.

Al ver que el propietario del process restante era DefaultAppPool, lo siguiente que probé fue detener IIS (esta database se está utilizando desde una aplicación ASP.Net). Lamentablemente, esto tampoco mató el process.

Eliminar manualmente el process del server sql restante elimina el identificador de file abierto en los files de la database, lo que permite que se copien / muevan.

Desafortunadamente, deseo copyr / restaurar esos files en algunas tareas previas o posteriores a la installation de un instalador de WiX; como tal, esperaba que hubiera una forma de lograr esto al detener un service de Windows, en lugar de tener que desembolsar todas las instancias de sqlserver.exe ya que plantea algunos problemas:

  1. La eliminación de todas las instancias de sqlserver.exe puede tener consecuencias no deseadas para los usuarios con otras instancias de Sql Server en sus máquinas.
  2. No puedo reiniciar esas instancias fácilmente.
  3. Presenta complejidades adicionales en el instalador.

¿Alguien tiene más ideas sobre cómo cerrar instancias del server sql asociado a una instancia de usuario específica?

Use "SQL Server Express Utility" (SSEUtil.exe) o el command para separar la database utilizada por SSEUtil.

Utilidad SQL Server Express, SSEUtil es una herramienta que le permite interactuar fácilmente con SQL Server, http://www.microsoft.com/downloads/details.aspx?FamilyID=fa87e828-173f-472e-a85c-27ed01cf6b02&DisplayLang=en

Además, el time de espera pnetworkingeterminado para detener el service después de cerrar la última connection es de una hora. En su cuadro de desarrollo, es posible que desee cambiar esto a cinco minutos (el mínimo permitido).

Además, puede tener una connection abierta a través de las conexiones de datos de Server Explorer de Visual Studio, así que asegúrese de desconectarse de cualquier database allí.

 H:\Tools\SQL Server Express Utility>sseutil -l 1. master 2. tempdb 3. model 4. msdb 5. C:\DEV_\APP\VISUAL STUDIO 2008\PROJECTS\MISSICO.LIBRARY.1\CLIENTS\CORE.DATA.C LIENT\BIN\DEBUG\CORE.DATA.CLIENT.MDF H:\Tools\SQL Server Express Utility>sseutil -d C:\DEV* Failed to detach 'C:\DEV_\APP\VISUAL STUDIO 2008\PROJECTS\MISSICO.LIBRARY.1\CLIE NTS\CORE.DATA.CLIENT\BIN\DEBUG\CORE.DATA.CLIENT.MDF' H:\Tools\SQL Server Express Utility>sseutil -l 1. master 2. tempdb 3. model 4. msdb H:\Tools\SQL Server Express Utility> 

Usando .NET Refector, el siguiente command se usa para separar la database.

 string.Format("USE master\nIF EXISTS (SELECT * FROM sysdatabases WHERE name = N'{0}')\nBEGIN\n\tALTER DATABASE [{1}] SET OFFLINE WITH ROLLBACK IMMEDIATE\n\tEXEC sp_detach_db [{1}]\nEND", dbName, str); 

He estado utilizando el siguiente método de ayuda para separar los files MDF adjuntos a SQL Server en testings unitarias (para que SQ Server libere lockings en files MDF y LDF y la testing unitaria puede limpiarse después de sí misma) …

 private static void DetachDatabase(DbProviderFactory dbProviderFactory, string connectionString) { using (var connection = dbProviderFactory.CreateConnection()) { if (connection is SqlConnection) { SqlConnection.ClearAllPools(); // convert the connection string (to connect to 'master' db), extract original database name var sb = dbProviderFactory.CreateConnectionStringBuilder(); sb.ConnectionString = connectionString; sb.Remove("AttachDBFilename"); var databaseName = sb["database"].ToString(); sb["database"] = "master"; connectionString = sb.ToString(); // detach the original database now connection.ConnectionString = connectionString; connection.Open(); using (var cmd = connection.CreateCommand()) { cmd.CommandText = "sp_detach_db"; cmd.CommandType = CommandType.StonetworkingProcedure; var p = cmd.CreateParameter(); p.ParameterName = "@dbname"; p.DbType = DbType.String; p.Value = databaseName; cmd.Parameters.Add(p); p = cmd.CreateParameter(); p.ParameterName = "@skipchecks"; p.DbType = DbType.String; p.Value = "true"; cmd.Parameters.Add(p); p = cmd.CreateParameter(); p.ParameterName = "@keepfulltextindexfile"; p.DbType = DbType.String; p.Value = "false"; cmd.Parameters.Add(p); cmd.ExecuteNonQuery(); } } } } 

Notas:

  • SqlConnection.ClearAllPools () fue muy útil para eliminar conexiones "sigilosas" (cuando se agrupa una connection, se mantendrá activa aunque la 'Cierre ()'; al eliminar explícitamente las conexiones de grupo, no tiene que preocuparse por establecer la agrupación bandera a falso en todas las cadenas de connection).
  • El "ingnetworkingiente mágico" es una llamada al procedimiento almacenado del sistema sp_detach_db (Transact-SQL) .
  • Mis cadenas de connection incluían "AttachDBFilename" pero no incluía "User Instance = True", por lo que esta solución podría no aplicarse a su escenario

No puedo comentar todavía porque aún no tengo suficiente representante. ¿Alguien puede mover esta información a la otra respuesta para que no tengamos una estafa?

Acabo de utilizar esta publicación para resolver mi problema de desinstallation de WIX. Utilicé esta línea de la respuesta de AMissico.

 string.Format("USE master\nIF EXISTS (SELECT * FROM sysdatabases WHERE name = N'{0}')\nBEGIN\n\tALTER DATABASE [{1}] SET OFFLINE WITH ROLLBACK IMMEDIATE\n\tEXEC sp_detach_db [{1}]\nEND", dbName, str); 

Funcionó bastante bien cuando usé WIX, solo tuve que agregar una cosa para que funcionara para mí.

Saqué el sp_detach_db y luego volví a conectar el db. Si no lo hace, WIX dejará los files mdf después de la desinstallation. Una vez que devolví el db en línea, WIX eliminaría correctamente los files mdf.

Aquí está mi línea modificada.

 string.Format( "USE master\nIF EXISTS (SELECT * FROM sysdatabases WHERE name = N'{0}')\nBEGIN\n\tALTER DATABASE [{0}] SET OFFLINE WITH ROLLBACK IMMEDIATE\n\tALTER DATABASE [{0}] SET ONLINE\nEND", dbName ); 

Puede que esto no sea lo que está buscando, pero la herramienta gratuita Unlocker tiene una interfaz de command-line que se puede ejecutar desde WIX. (He usado unlocker por un time y lo he encontrado estable y muy bueno en lo que hace mejor, desbloqueando files.)

Unlocker puede desbloquear y mover / eliminar la mayoría de los files.

La desventaja de esto es que las aplicaciones que necesitan un locking en el file ya no lo tendrán. (Pero a veces todavía funciona bien.) Tenga en count que esto no mata el process que tiene el locking. Simplemente elimina su locking. (Puede ser que reiniciar los services sql que está deteniendo sea suficiente para que vuelva a bloquear y / o funcione correctamente).

Puedes get Unlocker desde aquí: http://www.emptyloop.com/unlocker/

Para ver las opciones de línea de command, ejecute el unlocker -H Aquí están para mayor comodidad:

 Unlocker 1.8.8

 Uso de línea de command:
    Objeto Unlocker.exe [Opción]
 Objeto:
    Ruta completa que incluye unidad a un file o carpeta
 Opciones:
    / H o -H o /?  o - ?: Mostrar el uso de la línea de command 
    / S o -S: desbloquea el object sin mostrar la GUI 
    / L o -L: Object es un file de text que contiene la list de files para desbloquear 
    / LU o -LU: similar a / L con una list unicode de files para desbloquear 
    / O o -O: genera el file de logging Unlocker-Log.txt en el directory Unlocker 
    / D o -D: Eliminar file 
    / R Object2 o -R Object2: cambiar el nombre del file, si / L o / LU se establece object2 puntos a un file de text que contiene el nuevo nombre de los files 
    / M Object2 o -M Object2: mover file, si / L o / LU se establece object2 points un file de text que contiene la nueva location de files 

Asumiendo que su objective era replace C: \ My App \ Data \ MyApp.mdf con un file de su instalador, querría algo así como unlocker C:\My App\Data\MyApp.mdf -S -D . Esto eliminaría el file para que pueda copyr uno nuevo.