Implementar las pertenencias a roles de base de datos en entornos de prueba

por Jason Lee

En este tema se describe cómo agregar cuentas de usuario a roles de base de datos como parte de la implementación de una solución en un entorno de prueba.

Al implementar una solución que contiene un proyecto de base de datos en un entorno de ensayo o producción, normalmente no quiere que el desarrollador automatice la adición de cuentas de usuario a roles de base de datos. En la mayoría de los casos, el desarrollador no sabrá qué cuentas de usuario deben agregarse a qué roles de base de datos y estos requisitos podrían cambiar en cualquier momento. Pero al implementar una solución que contiene un proyecto de base de datos en un entorno de desarrollo o prueba, la situación suele ser bastante diferente:

  • Normalmente, el desarrollador vuelve a implementar la solución de forma periódica, a menudo varias veces al día.
  • Normalmente, la base de datos se vuelve a crear en cada implementación, lo que significa que los usuarios de la base de datos deben crearse y agregarse a roles después de cada implementación.
  • Normalmente, el desarrollador tiene control total sobre el entorno de desarrollo o prueba de destino.

En este escenario, a menudo resulta beneficioso crear automáticamente usuarios de base de datos y asignar pertenencias a roles de base de datos como parte del proceso de implementación.

El factor clave es que esta operación debe ser condicional en función del entorno de destino. Si va a realizar la implementación en un entorno de ensayo o de producción, querrá omitir la operación. Si va a realizar la implementación en un entorno de desarrollo o prueba, querrá implementar pertenencias a roles sin intervención adicional. En este tema se describe un enfoque que puede usar para abordar este desafío.

Este tema forma parte de una serie de tutoriales basados en los requisitos de implementación empresarial de una empresa ficticia denominada Fabrikam, Inc. En esta serie de tutoriales se utiliza una solución de ejemplo (Contact Manager) para representar una aplicación web con un nivel de complejidad realista, que incluye una aplicación ASP.NET MVC 3, un servicio Windows Communication Foundation (WCF) y un proyecto de base de datos.

El método de implementación que constituye el núcleo de estos tutoriales se basa en el enfoque del archivo de proyecto dividido descrito en Descripción del archivo del proyecto, en el que el proceso de compilación está controlado por dos archivos de proyecto: uno que contiene las instrucciones de compilación que se aplican a todos los entornos de destino y otro que contiene los ajustes de compilación e implementación específicos del entorno. En tiempo de compilación, el archivo del proyecto específico del entorno se combina en el archivo del proyecto independiente del entorno para formar un conjunto completo de instrucciones de compilación.

Resumen de las tareas

En este tema se supone que:

Para crear usuarios de base de datos y asignar pertenencias a roles al implementar un proyecto de base de datos en un entorno de prueba, deberá hacer lo siguiente:

  • Crear un script de Lenguaje de consulta estructurado Transact (Transact-SQL) que realice los cambios necesarios en la base de datos.
  • Crear un destino de Microsoft Build Engine (MSBuild) que use la utilidad sqlcmd.exe para ejecutar el script SQL.
  • Configurar los archivos del proyecto para invocar el destino al implementar la solución en un entorno de prueba.

En este tema se explica cómo realizar cada uno de estos procedimientos.

Creación de scripts de pertenencia a roles de base de datos

Puede crear un script de Transact-SQL de muchas maneras diferentes y en cualquier ubicación que elija. El enfoque más sencillo es crear el script dentro de la solución en Visual Studio 2010.

Para crear un script SQL

  1. En la ventana Explorador de soluciones, expanda el nodo del proyecto de base de datos.

  2. Haga clic con el botón derecho en la carpeta Scripts, seleccione Agregar y, después, haga clic en Nueva carpeta.

  3. Escriba Test como el nombre de la carpeta y presione Entrar.

  4. Haga clic con el botón derecho en la carpeta Test, seleccione Agregar y, después, haga clic en Script.

  5. En el cuadro de diálogo Agregar nuevo elemento, asigne un nombre descriptivo al script (por ejemplo, AddRoleMemberships.sql) y, después, haga clic en Agregar.

    In the Add New Item dialog box, give your script a meaningful name (for example, AddRoleMemberships.sql), and then click Add.

  6. En el archivo AddRoleMemberships.sql, agregue instrucciones Transact-SQL que hagan lo siguiente:

    1. Crear un usuario de base de datos para el inicio de sesión de SQL Server que accederá a la base de datos.
    2. Agregar el usuario de base de datos a los roles de base de datos necesarios.
  7. El código debe ser similar a este:

    USE $(DatabaseName)
    GO
    CREATE USER [FABRIKAM\TESTWEB1$] FOR LOGIN[FABRIKAM\TESTWEB1$]
    GO
    USE [ContactManager]
    GO
    EXEC sp_addrolemember N'db_datareader', N'FABRIKAM\TESTWEB1$'
    GO
    USE [ContactManager]
    GO
    EXEC sp_addrolemember N'db_datawriter', N'FABRIKAM\TESTWEB1$'
    GO
    
  8. Guarde el archivo.

Ejecución del script en la base de datos de destino

Idealmente, ejecutaría los scripts de Transact-SQL necesarios como parte de un script posterior a la implementación al implementar el proyecto de base de datos. Pero los scripts posteriores a la implementación no permiten ejecutar lógica condicionalmente en función de las configuraciones de la solución ni de las propiedades de compilación. La alternativa es ejecutar los scripts SQL directamente desde el archivo del proyecto de MSBuild mediante la creación de un elemento Target que ejecute un comando sqlcmd.exe. Puede usar este comando para ejecutar el script en la base de datos de destino:

sqlcmd.exe –S [Database server] –d [Database name] –i [SQL script]

Nota:

Para más información sobre las opciones de la línea de comandos de sqlcmd, vea Utilidad sqlcmd.

Antes de insertar este comando en un destino de MSBuild, debe tener en cuenta en qué condiciones quiere que se ejecute el script:

  • La base de datos de destino debe existir antes de cambiar sus pertenencias a roles. Por tanto, debe ejecutar este script después de la implementación de la base de datos.
  • Debe incluir una condición para que el script solo se ejecute para entornos de prueba.
  • Si ejecuta una implementación "hipotética" (es decir, si va a generar scripts de implementación pero sin ejecutarlos realmente) no debe ejecutar el script SQL.

Si usa el enfoque de archivo de proyecto dividido descrito en Descripción del archivo del proyecto, como se ha mostrado en la solución de ejemplo Contact Manager, puede dividir las instrucciones de compilación para el script SQL de la siguiente manera:

  • Todas las propiedades específicas del entorno necesarias, junto con la propiedad que determina si se van a implementar permisos, deben ir en el archivo del proyecto específico del entorno (por ejemplo, Env-Dev.proj).
  • El propio destino de MSBuild, junto con las propiedades que no cambiarán entre entornos de destino, debe ir en el archivo del proyecto universal (por ejemplo, Publish.proj).

En el archivo del proyecto específico del entorno, debe definir el nombre del servidor de base de datos, el nombre de la base de datos de destino y una propiedad booleana que permita al usuario especificar si se van a implementar pertenencias a roles.

<PropertyGroup>
   <CmTargetDatabase Condition=" '$(CmTargetDatabase)'=='' ">
      ContactManager
   </CmTargetDatabase>
   <DatabaseServer Condition=" '$(DatabaseServer)'=='' ">
      TESTDB1
   </DatabaseServer>
   <DeployTestDBRoleMemberships Condition="'$(DeployTestDBRoleMemberships)'==''">
      true
   </DeployTestDBRoleMemberships>
</PropertyGroup>

En el archivo del proyecto universal, debe proporcionar la ubicación del ejecutable sqlcmd y la del script SQL que quiere ejecutar. Estas propiedades seguirán siendo las mismas independientemente del entorno de destino. También debe crear un destino de MSBuild para ejecutar el comando sqlcmd.

<PropertyGroup>
   <SqlCmdExe Condition=" '$(SqlCmdExe)'=='' ">
      C:\Program Files\Microsoft SQL Server\100\Tools\Binn\sqlcmd.exe
   </SqlCmdExe>
</PropertyGroup>

<Target Name="DeployTestDBPermissions" 
        Condition=" '$(DeployTestDBRoleMemberships)'=='true' AND 
                    '$(Whatif)'!='true' ">
   <PropertyGroup>
     <SqlScript>
        $(SourceRoot)ContactManager.Database\Scripts\Test\AddRoleMemberships.sql
     </SqlScript>
     <_Cmd>"$(SqlCmdExe)" -S "$(DatabaseServer)" 
                          -d "$(CmTargetDatabase)" 
                          -i "$(SqlScript)"
     </_Cmd>
   </PropertyGroup>
   <Exec Command="$(_Cmd)" ContinueOnError="false" />
</Target>

Tenga en cuenta que la ubicación del ejecutable sqlcmd se agrega como una propiedad estática, ya que esto podría ser útil para otros destinos. En cambio, definirá la ubicación del script SQL y la sintaxis del comando sqlcmd como propiedades dinámicas dentro del destino, ya que no serán necesarias antes de que se ejecute el destino. En este caso, el destino DeployTestDBPermissions solo se ejecutará si se cumplen estas condiciones:

  • La propiedad DeployTestDBRoleMemberships se establece en true.
  • El usuario no ha especificado una marca WhatIf=true.

Por último, no olvide invocar el destino. En el archivo Publish.proj, puede hacerlo si agrega el destino a la lista de dependencias para el destino FullPublish predeterminado. Debe asegurarse de que el destino DeployTestDBPermissions no se ejecute hasta que se haya ejecutado el destino PublishDbPackages.

<Project ToolsVersion="4.0" 
         DefaultTargets="FullPublish" 
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   ...
   <PropertyGroup>
      <FullPublishDependsOn>
         Clean;
         BuildProjects;
         GatherPackagesForPublishing;
         PublishDbPackages;
         DeployTestDBPermissions;
         PublishWebPackages;
      </FullPublishDependsOn>
   </PropertyGroup>
   <Target Name="FullPublish" DependsOnTargets="$(FullPublishDependsOn)" />
</Project>

Conclusión

En este tema se ha descrito una manera de agregar usuarios de base de datos y pertenencias a roles como una acción posterior a la implementación al implementar un proyecto de base de datos. Esto suele ser útil cuando se vuelve a crear regularmente una base de datos en un entorno de prueba, pero normalmente se debe evitar al implementar bases de datos en entornos de ensayo o producción. Por tanto, debe asegurarse de que usa la lógica condicional necesaria para que los usuarios de la base de datos y las pertenencias a roles solo se creen cuando sea adecuado hacerlo.

Lecturas adicionales

Para más información sobre el uso de VSDBCMD para implementar proyectos de base de datos, vea Implementación de proyectos de base de datos. Para obtener instrucciones sobre cómo personalizar las implementaciones de bases de datos para distintos entornos de destino, vea Personalización de implementaciones de base de datos para varios entornos. Para más información sobre el uso de archivos del proyecto de MSBuild personalizados para controlar el proceso de implementación, vea Descripción del archivo del proyecto y Descripción del proceso de compilación. Para más información sobre las opciones de la línea de comandos de sqlcmd, vea Utilidad sqlcmd.