Hola ¿Qué tal?...
Continuando con las utilidades de SQL Server con ADO.NET toca el turno a una nueva funcionalidad que puede ser de gran ayuda al momento de cambiar de nombre a una base de datos de SQL Server.
Esta funcionalidad podrá ser utilizada con bases de datos de SQL Server 2000 y 2005, aunque en ocasiones tendré que especificar si es posible en versiones anteriores a SQL Server 2005 ya que estaré publicando estas utilidades principalmente para funcionar en SQL Server 2005.
Separar y Adjuntar los Archivos de una Base de Datos de SQL Server con T-SQL
Separar una base de datos del servidor es útil en contadas ocasiones, casi siempre es mejor realizar respaldos de las bases de datos, sin embargo hay escenarios en los que la recuperación de bases de datos no es tarea fácil, y esto es porque en un respaldo se guarda la ruta original del archivo ya que está pensada la restauración para ser ejecutada en el mismo servidor donde se realizó el respaldo. En ocasiones cuando se necesita mover una base de datos de un servidor a otro la mejor manera es separando la base de datos, de esta manera los archivos quedan libres y se pueden adjuntar en un nuevo servidor sin mucho problema, el único detalle es que los trabajos programados no se van con la base de datos, ni aún con los respaldos, dado que los trabajos son registrados en las bases de datos de sistema.
Para la tarea de cambiar el nombre de la base de datos nos será útil la capacidad de SQL Server de separar los archivos del servidor, de esta manera, podremos cambiar el nombre del archivo para volverlo a adjuntar, una vez adjuntados será útil realizar el procedimiento que he descrito con anterioridad en este artículo.
Veamos la manera de realizar la separación de la base de datos del servidor utilizando T-SQL:
--Ejecutado de manera directa
EXEC sp_detach_db AdventureWorks--Ejecutad con asiganción explícita
--del parámetro @dbname
EXEC sp_detach_db @dbname=AdventureWorks
Se utiliza el procedimiento almacenado de sistema sp_detach_db, cuyos parámetros son tres, sin embargo es suficiente con el parámetro de base de datos ya que el segundo parámetro es para indicar si se omite la instrucción UPDATE STATISTICS sobre todas las tablas de la base de datos. UPDATE STATISTICS se ejecuta de manera predeterminada sobre todas las tablas de la base de datos antes de separarla si se omite este valor, lo cual es bueno pues deja a la base de datos lista para adjuntarse en otro servidor.
Cuando se separan los archivos de una base de datos estos quedan en el directorio de datos del servidor, este directorio de archivos de bases de datos comúnmente está en:
%programfiles%\Microsoft SQL Server\MSSQL.1\MSSQL\Data
Esto es para instancias de SQL Server 2005, aunque puede variar según la instancia del servidor donde se esté trabajando, la instancia se identifica por la carpeta MSSQL y el sufijo .n donde n es el número de la instancia.
Continuando con el tema de renombrar la base de datos, separamos la base de datos en cuestión y procederemos a cambiar el nombre de los archivos en congruencia con el nuevo nombre de la base de datos, esto es, que si el archivo se llama AdventureWorks_Data.mdf y el nuevo nombre de la base de datos será NewAdventureWorks, pues la congruencia sería renombrar el archivo a NewAdventureWorks_Data.mdf, de manera similar será con el archivo Log (ldf); así entonces, una vez cambiado el nombre de los archivos procedemos a adjuntaros. En versiones anteriores a SQL Server 2005 se utilizaba el procedimiento almacenado de sistema sp_attach_db, sin embargo, en SQL Server 2005 se utiliza la instrucción CREATE DATABASE para adjuntar una base de datos. En el siguiente ejemplo se muestra cómo adjuntar la base de datos que hemos modificado:
Create Database NewAdventureWorks
on
(FILENAME='C:\Archivos de programa\
Microsoft SQL Server\
MSSQL.1\MSSQL\Data\NewAdventureWorks_Data.mdf'),
(FILENAME='C:\Archivos de programa\
Microsoft SQL Server\
MSSQL.1\MSSQL\Data\NewAdventureWorks_Log.ldf')
For ATTACH
NOTA: la ruta del archivo debe quedar en una sola línea, sin espacios ni saltos de línea, aunque en el ejemplo se muestra con saltos de línea a causa de las limitaciones del ancho de esta publicación, ya que de otra manera causaría un error.
Al cambiar el nombre directamente de los archives nos da la oportunidad de definir el nuevo nombre de la base de datos al adjuntarlos nuevamente, lo único que quedará pendiente será cambiar los nombre de los archivos lógicos, con lo que estará completamente cambiado el nombre de la base de datos. Y digo cambiar completamente el nombre ya que el cambiar el nombre de la base de datos desde el SQL Server Management Studio no aplica los cambios en los archivos lógicos y físicos.
Separar y Adjuntar los Archivos de una Base de Datos de SQL Server con ADO.NET
Ahora nos enfocaremos a escribir los métodos necesarios para separar y adjuntar una base de datos de Sql Server, pero utilizando ADO.NET, para lo cual utilizaremos lo que vimos con T-SQL.
Primeramente crearemos el método que separa la base de datos. El siguiente ejemplo muestra cómo queda este método:
VB.NET
Public Sub DetachDataBase(ByVal DBName As String)
'Declaramos el SqlCommand que se usará
'para ejecutar el procedimiento almacenado
Dim cmd As SqlCommand = _
New SqlCommand("sp_detach_db")
'Se establece el tipo de Command que se
'usará, para este caso StoredProcedure
cmd.CommandType = CommandType.StoredProcedure
'Se agrega el parámetro @dbname que se
'utiliza para identificar la base de datos
'a separar
cmd.Parameters.Add("@dbname", _
SqlDbType.NVarChar, 128).Value = DBName
'Se asigna la conexión al command
cmd.Connection = cnn
Try
'se abre la conexión
cnn.Open()
'se ejecuta el command
cmd.ExecuteNonQuery()
Catch ex As SqlException
'se capturan los mensajes de error
mMessages = ex.Message
Finally
'se cierra la conexión al terminar
cnn.Close()
End Try
End Sub
C#
public void DetachDataBase(string DBName)
{
//Declaramos el SqlCommand que se usará
//para ejecutar el procedimiento almacenado
SqlCommand cmd =
new SqlCommand("sp_detach_db");
//Se establece el tipo de Command que se
//usará, para este caso StoredProcedure
cmd.CommandType = CommandType.StoredProcedure;
//Se agrega el parámetro @dbname que se
//utiliza para identificar la base de datos
//a separar
cmd.Parameters.Add("@dbname",
SqlDbType.NVarChar, 128).Value = DBName;
//Se asigna la conexión al command
cmd.Connection = cnn;
try
{
//se abre la conexión
cnn.Open();
//se ejecuta el command
cmd.ExecuteNonQuery();
}
catch (SqlException ex)
{
//se capturan los mensajes de error
messages = ex.Message;
}
finally
{
//se cierra la conexión al terminar
cnn.Close();
}
}
Aquí tenemos ya nuestro método para separa la base de datos, habrá que hacer algunas observaciones adicionales, como por ejemplo, el parámetro @dbname que utilizamos en T-SQL para pasar el nombre de la base de datos en el procedimiento almacenado sp_detach_db es del tipo sysname en T-SQL, este tipo es un tipo definido por el usuario en Sql Server, por lo que no podremos utilizarlo directamente, sin embargo tiene una equivalencia con NVarchar(128), por lo que utilizaremos este tipo y longitud en nuestro parámetro, lo cual es equivalente funcionalmente.
Ahora veremos cómo podremos adjuntar los archivos nuevamente. Este método será crucial para el objetivo principal que es cambiar el nombre a la base de datos y es que será el que realmente cambie el nombre de la base de datos ya que al adjuntar los archivos, debemos especificar un nombre en la base de datos, con lo que estaremos definiendo el nombre que nos interesa.
El siguiente ejemplo muestra el método que realizará la tarea de adjuntar la base de datos al servidor:
VB.NET
Public Sub AttachDataBase(ByVal DBName As String, _
ByVal Files As List(Of String))
'Se declara el SqlCommand que ejecutará la
'instrucción
Dim cmd As SqlCommand = New SqlCommand()
'Se declara un string donde se construirá
'la cadena de la instrucción
Dim strSql As String
'Se contruye la primera parte de la instrucción
strSql = String.Format("Create Database {0} on ", DBName)
'Se agreagan las rutas de archivos que usará
'la instrucción CREATE DATABASE
For Each str As String In Files
strSql &= String.Format("(FILENAME='{0}'),", str)
Next
'Se remueve la útlima coma de la cadena
strSql = strSql.Remove(strSql.Length - 1)
'Se completa la instrucción
strSql &= " FOR ATTACH"
'Se asigna la instrucción al SqlCommand
cmd.CommandText = strSql
'Se asigna la conexión al SqlCommand
cmd.Connection = cnn
'Se intenta ejecutar el SqlCommand
Try
'Se abre la conexión
cnn.Open()
'Se ejecuta la instrucción
cmd.ExecuteNonQuery()
Catch ex As SqlException
'Se capturan los mensajes de error
mMessages = ex.Message
Finally
'Se cierra la conexión
cnn.Close()
End Try
End Sub
C#
public void AttachDataBase(String DBName,
List<string> Files)
{
//Se declara el SqlCommand que ejecutará la
//instrucción
SqlCommand cmd = new SqlCommand();
//Se declara un string donde se construirá
//la cadena de la instrucción
String strSql;
//Se contruye la primera parte de la instrucción
strSql = String.Format("Create Database {0} on ", DBName);
//Se agreagan las rutas de archivos que usará
//la instrucción CREATE DATABASE
foreach (String str in Files)
{
strSql += String.Format("(FILENAME='{0}'),", str);
}
//Se remueve la útlima coma de la cadena
strSql = strSql.Remove(strSql.Length - 1);
//Se completa la instrucción
strSql += " FOR ATTACH";
//Se asigna la instrucción al SqlCommand
cmd.CommandText = strSql;
//Se asigna la conexión al SqlCommand
cmd.Connection = cnn;
//Se intenta ejecutar el SqlCommand
try
{
//Se abre la conexión
cnn.Open();
//Se ejecuta la instrucción
cmd.ExecuteNonQuery();
}
catch (SqlException ex)
{
//Se capturan los mensajes de error
messages = ex.Message;
}
finally
{
//Se cierra la conexión
cnn.Close();
}
}
Con esto tendremos listo el método para adjuntar la base de datos. Nótese que he usado un parámetro de lista genérica para pasar la ruta de los archivos que se usaran para adjuntar la base de datos. Si no se agrega el archivo Log, SQL Server intentará crear uno nuevo.
Conclusiones
Como hemos visto hasta ahora, realizar la transformación de T-SQL a ADO.NET ha sido completamente sencillo ya que solo hemos tenido que asignar las instrucciones T-SQL al CommandText de nuestra variable de SqlCommand, seguido solo asignamos la conexión, abrimos la conexión y ejecutamos el SqlCommand. Las demás utilidades que estaré publicando, se hacen de la misma manera.
Recuerden que este método está pensado en el diseño original de la clase SqlUtilities que creamos en la primera publicación de la serie el cual está aquí:
http://msmvps.com/blogs/otelis/archive/2007/06/19/utilidades-de-sql-server-con-ado-net-regenerar-campos-identity.aspx
He decidido publicar segmentos más cortos para mejor asimilación, este es el primer segmento de la serie que terminará en el método que automatiza el cambio de nombre de una base de datos por completo, así que estén pendientes.
Espero que haya sido de utilidad, nos vemos en el próximo post.
Saludos…
Octavio Telis