Implementación de una aplicación web de ASP.NET con SQL Server Compact mediante Visual Studio o Visual Web Developer: Implementación de bases de datos de SQL Server Compact: 2 de 12

por Tom Dykstra

Descargar el proyecto de inicio

En esta serie de tutoriales se muestra cómo implementar (publicar) un proyecto de aplicación web de ASP.NET que incluye una base de datos de SQL Server Compact mediante Visual Studio 2012 RC o Visual Studio Express 2012 RC para la web. También puede usar Visual Studio 2010 si instala la actualización de publicación web. Para obtener una introducción a la serie, consulte el primer tutorial de la serie.

Para ver un tutorial que muestra las características de implementación introducidas después de la versión RC de Visual Studio 2012, muestra cómo implementar ediciones de SQL Server distintas de SQL Server Compact y muestra cómo implementar en Azure App Service Web Apps, consulte Implementación web de ASP.NET con Visual Studio.

Información general

En este tutorial se muestra cómo configurar dos bases de datos de SQL Server Compact y el motor de base de datos para la implementación.

Para el acceso a la base de datos, la aplicación Contoso University requiere el siguiente software que se debe implementar con la aplicación porque no se incluye en .NET Framework:

También se deben implementar la estructura de la base de datos y algunos de los datos de las dos bases de datos de la aplicación. Normalmente, a medida que desarrolla una aplicación, se introducen datos de prueba en una base de datos que no desea implementar en un sitio activo. Sin embargo, también puede escribir algunos datos de producción que quiera implementar. En este tutorial configurará el proyecto Contoso University para que se incluyan el software necesario y los datos correctos al implementar.

Aviso: Si recibe un mensaje de error o algo no funciona mientras recorre el tutorial, asegúrese de comprobar la página de solución de problemas.

SQL Server Compact frente a SQL Server Express

La aplicación de ejemplo usa SQL Server Compact 4.0. Este motor de base de datos es una opción relativamente nueva para sitios web. Las versiones anteriores de SQL Server Compact no funcionan en un entorno de hospedaje web. SQL Server Compact ofrece algunas ventajas en comparación con el escenario más común de desarrollo con SQL Server Express e implementación en SQL Server completo. En función del proveedor de hospedaje que elija, implementar SQL Server Compact podría ser más barato, ya que algunos proveedores cobran un cargo adicional para admitir una base de datos completa de SQL Server. No hay ningún cargo adicional por SQL Server Compact porque puede implementar el propio motor de base de datos como parte de la aplicación web.

Sin embargo, también debe tener en cuenta sus limitaciones. SQL Server Compact no admite procedimientos almacenados, desencadenadores, vistas ni replicación. (Para obtener una lista completa de las características de SQL Server que no son compatibles con SQL Server Compact, consulte Diferencias entre SQL Server Compact y SQL Server). Además, algunas de las herramientas que puede usar para manipular esquemas y datos en bases de datos de SQL Server Express y SQL Server no funcionan con SQL Server Compact. Por ejemplo, no puede usar SQL Server Management Studio ni SQL Server Data Tools en Visual Studio con bases de datos de SQL Server Compact. Tiene otras opciones para trabajar con bases de datos de SQL Server Compact:

  • Puede usar el Explorador de servidores en Visual Studio, que ofrece una funcionalidad limitada de manipulación de bases de datos para SQL Server Compact.
  • Puede usar la característica de manipulación de la base de datos de WebMatrix, que tiene más características que el Explorador de servidores.
  • Puede usar herramientas de código abierto o de terceros relativamente completas, como el cuadro de herramientas de SQL Server Compact y la utilidad de scripts de esquema y datos de SQL Compact.
  • Puede escribir y ejecutar sus propios scripts DDL (lenguaje de definición de datos) para manipular el esquema de la base de datos.

Puede empezar con SQL Server Compact y, a continuación, actualizarlo más adelante a medida que evolucionan sus necesidades. Los tutoriales posteriores de esta serie muestran cómo migrar de SQL Server Compact a SQL Server Express y a SQL Server. Sin embargo, si va a crear una nueva aplicación y espera necesitar SQL Server en un futuro próximo, es probable que sea mejor empezar con SQL Server o SQL Server Express.

Configuración del motor de base de datos de SQL Server Compact para la implementación

El software necesario para el acceso a datos en la aplicación Contoso University se agregó mediante la instalación de los siguientes paquetes NuGet:

Los vínculos apuntan a las versiones actuales de estos paquetes, que podrían ser más recientes que lo que se instala en el proyecto de inicio que descargó para este tutorial. Para la implementación en un proveedor de hospedaje, asegúrese de usar Entity Framework 5.0 o posterior. Las versiones anteriores de las migraciones de Code First requieren plena confianza y, en muchos proveedores de hospedaje, la aplicación se ejecutará en confianza media. Para obtener más información sobre la confianza media, consulte el tutorial Implementación en IIS como entorno de prueba.

La instalación de paquetes NuGet generalmente se encarga de todo lo que necesita para implementar este software con la aplicación. En algunos casos, esto implica tareas como cambiar el archivo Web.config y agregar scripts de PowerShell que se ejecutan cada vez que se compila la solución. Si desea agregar compatibilidad con cualquiera de estas características (como SQL Server Compact y Entity Framework) sin usar NuGet, asegúrese de que sabe lo que hace la instalación del paquete NuGet para que pueda hacer el mismo trabajo manualmente.

Hay una excepción en la que NuGet no se encarga de todo lo que tiene que hacer para garantizar una implementación correcta. El paquete NuGet SqlServerCompact agrega un script posterior a la compilación al proyecto que copia los ensamblados nativos en subcarpetas x86 y amd64 en la carpeta bin del proyecto, pero el script no incluye esas carpetas en el proyecto. Como resultado, Web Deploy no los copiará en el sitio web de destino a menos que los incluya manualmente en el proyecto. (Este comportamiento resulta de la configuración de implementación predeterminada; otra opción, que no se usará en estos tutoriales, es cambiar la configuración que controla este comportamiento. La configuración que puede cambiar es Solo los archivos necesarios para ejecutar la aplicación en Elementos para realizar la implementación en la pestaña Paquete/Publicar web de la ventana Propiedades del proyecto. No se recomienda cambiar esta configuración por lo general porque puede dar lugar a la implementación de muchos más archivos en el entorno de producción de los que se necesitan en él. Para obtener más información sobre las alternativas, consulte el tutorial Configuración de propiedades del proyecto).

Compile el proyecto y, a continuación, en el Explorador de soluciones, haga clic en Mostrar todos los archivos si aún no lo ha hecho. También puede que tenga que hacer clic en Actualizar.

Solution_Explorer_Show_All_Files

Expanda la carpeta bin para ver las carpetas amd64 y x86 y, a continuación, seleccione esas carpetas, haga clic con el botón derecho y seleccione Incluir en Project.

amd64_and_x86_in_Solution_Explorer.png

Los iconos de carpeta cambian para mostrar que la carpeta se ha incluido en el proyecto.

Solution_Explorer_amd64_included.png

Configuración de migraciones de Code First para la implementación de bases de datos de aplicaciones

Al implementar una base de datos de aplicación, normalmente no solo se implementa la base de datos de desarrollo con todos los datos en ella en producción, ya que gran parte de los datos en ella probablemente solo están allí con fines de prueba. Por ejemplo, los nombres de los alumnos de una base de datos de prueba son ficticios. Por otro lado, a menudo no se puede implementar solo la estructura de la base de datos sin datos en ella. Algunos de los datos de la base de datos de prueba pueden ser datos reales y deben estar allí cuando los usuarios empiecen a usar la aplicación. Por ejemplo, la base de datos puede tener una tabla que contenga valores de notas válidos o nombres de departamento reales.

Para simular este escenario común, configurará un método de inicialización de migraciones de Code First que inserta en la base de datos solo los datos que desea que estén en producción. Este método Seed no insertará datos de prueba porque se ejecutará en producción después de que Code First cree la base de datos en producción.

En versiones anteriores de Code First antes de que se publicaran migraciones, era habitual que los métodos de inicialización insertaran datos de prueba también, ya que con cada cambio de modelo durante el desarrollo, la base de datos tenía que eliminarse y volver a crearse desde cero. Con las migraciones de Code First, los datos de prueba se conservan después de los cambios en la base de datos, por lo que no es necesario incluir datos de prueba en el método Seed. El proyecto que descargó usa el método de premigraciones de incluir todos los datos en el método Seed de una clase de inicializador. En este tutorial deshabilitará la clase de inicializador y habilitará Migraciones. A continuación, actualizará el método Seed en la clase de configuración de Migraciones para que inserte solo los datos que desea insertar en producción.

En el diagrama siguiente se muestra el esquema de la base de datos de aplicación:

School_database_diagram

En estos tutoriales, se supone que las tablas Student y Enrollment deben estar vacías cuando el sitio se implemente por primera vez. Las demás tablas contienen datos que tienen que cargarse previamente cuando la aplicación pasa a estar activa.

Puesto que va a usar migraciones de Code First, ya no tiene que usar el inicializador de Code First DropCreateDatabaseIfModelChanges. El código de este inicializador se encuentra en el archivo SchoolInitializer.cs del proyecto ContosoUniversity.DAL. Un valor en el elemento appSettings del archivo Web.config hace que este inicializador se ejecute siempre que la aplicación intente acceder a la base de datos por primera vez:

<appSettings>
  <add key="Environment" value="Dev" />
  <add key="DatabaseInitializerForType ContosoUniversity.DAL.SchoolContext, ContosoUniversity.DAL" value="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity.DAL" />
</appSettings>

Abra el archivo Web.config de la aplicación y quite el elemento que especifica la clase de inicializador de Code First del elemento appSettings. El elemento appSettings ahora tiene el siguiente aspecto:

<appSettings>
  <add key="Environment" value="Dev" />
</appSettings>

Nota:

Otra manera de especificar una clase de inicializador es llamar a Database.SetInitializer en el método Application_Start del archivo Global.asax. Si va a habilitar Migraciones en un proyecto que usa ese método para especificar el inicializador, quite esa línea de código.

A continuación, habilite Migraciones de Code First.

El primer paso es asegurarse de que el proyecto ContosoUniversity está establecido como proyecto de inicio. En Explorador de soluciones, haga clic con el botón derecho en el proyecto ContosoUniversity y seleccione Establecer como proyecto de inicio. Las migraciones de Code First buscarán en el proyecto de inicio para encontrar la cadena de conexión de la base de datos.

En el menú Tools (Herramientas), haga clic en Administrador de paquetes NuGet y luego en Consola del Administrador de paquetes.

Selecting_Package_Manager_Console

En la parte superior de la ventana Consola del administrador de paquetes, seleccione ContosoUniversity.DAL como proyecto predeterminado y, a continuación, en la confirmación PM>, escriba "enable-migrations".

enable-migrations_command

Este comando crea un archivo Configuration.cs en una nueva carpeta Migraciones del proyecto ContosoUniversity.DAL.

Migrations_folder_in_Solution_Explorer

Ha seleccionado el proyecto DAL porque el comando "enable-migrations" debe ejecutarse en el proyecto que contiene la clase de contexto Code First. Cuando esa clase se encuentra en un proyecto de biblioteca de clases, Migraciones de Code First busca la cadena de conexión de base de datos en el proyecto de inicio de la solución. En la solución ContosoUniversity, el proyecto web se ha establecido como proyecto de inicio. (Si no desea designar el proyecto que tiene la cadena de conexión como proyecto de inicio en Visual Studio, puede especificar el proyecto de inicio en el comando de PowerShell. Para ver la sintaxis del comando enable-migrations, puede escribir el comando "get-help enable-migrations".

Abra el archivo Configuration.cs y reemplace los comentarios del método Seed por el código siguiente:

var instructors = new List<Instructor>
{   
    new Instructor { FirstMidName = "Kim",     LastName = "Abercrombie", HireDate = DateTime.Parse("1995-03-11"), OfficeAssignment = new OfficeAssignment { Location = "Smith 17" } },
    new Instructor { FirstMidName = "Fadi",    LastName = "Fakhouri",    HireDate = DateTime.Parse("2002-07-06"), OfficeAssignment = new OfficeAssignment { Location = "Gowan 27" } },
    new Instructor { FirstMidName = "Roger",   LastName = "Harui",       HireDate = DateTime.Parse("1998-07-01"), OfficeAssignment = new OfficeAssignment { Location = "Thompson 304" } },
    new Instructor { FirstMidName = "Candace", LastName = "Kapoor",      HireDate = DateTime.Parse("2001-01-15") },
    new Instructor { FirstMidName = "Roger",   LastName = "Zheng",       HireDate = DateTime.Parse("2004-02-12") }
};
instructors.ForEach(s => context.Instructors.AddOrUpdate(i => i.LastName, s));
context.SaveChanges();

var departments = new List<Department>
{
    new Department { Name = "English",     Budget = 350000, StartDate = DateTime.Parse("2007-09-01"), PersonID = 1 },
    new Department { Name = "Mathematics", Budget = 100000, StartDate = DateTime.Parse("2007-09-01"), PersonID = 2 },
    new Department { Name = "Engineering", Budget = 350000, StartDate = DateTime.Parse("2007-09-01"), PersonID = 3 },
    new Department { Name = "Economics",   Budget = 100000, StartDate = DateTime.Parse("2007-09-01"), PersonID = 4 }
};
departments.ForEach(s => context.Departments.AddOrUpdate(d => d.Name, s));
context.SaveChanges();

var courses = new List<Course>
{
    new Course { CourseID = 1050, Title = "Chemistry",      Credits = 3, DepartmentID = 3, Instructors = new List<Instructor>() },
    new Course { CourseID = 4022, Title = "Microeconomics", Credits = 3, DepartmentID = 4, Instructors = new List<Instructor>() },
    new Course { CourseID = 4041, Title = "Macroeconomics", Credits = 3, DepartmentID = 4, Instructors = new List<Instructor>() },
    new Course { CourseID = 1045, Title = "Calculus",       Credits = 4, DepartmentID = 2, Instructors = new List<Instructor>() },
    new Course { CourseID = 3141, Title = "Trigonometry",   Credits = 4, DepartmentID = 2, Instructors = new List<Instructor>() },
    new Course { CourseID = 2021, Title = "Composition",    Credits = 3, DepartmentID = 1, Instructors = new List<Instructor>() },
    new Course { CourseID = 2042, Title = "Literature",     Credits = 4, DepartmentID = 1, Instructors = new List<Instructor>() }
};
courses.ForEach(s => context.Courses.AddOrUpdate(s));
context.SaveChanges();

courses[0].Instructors.Add(instructors[0]);
courses[0].Instructors.Add(instructors[1]);
courses[1].Instructors.Add(instructors[2]);
courses[2].Instructors.Add(instructors[2]);
courses[3].Instructors.Add(instructors[3]);
courses[4].Instructors.Add(instructors[3]);
courses[5].Instructors.Add(instructors[3]);
courses[6].Instructors.Add(instructors[3]);
context.SaveChanges();

Las referencias a List tienen líneas onduladas rojas bajo ellas porque aún no tiene una instrucción using para su espacio de nombres. Haga clic con el botón derecho en una de las instancias de List y haga clic en Resolver y, a continuación, haga clic en Usar System.Collections.Generic.

Resolve with using statement

Esta selección de menú agrega el código siguiente a las instrucciones using cerca de la parte superior del archivo.

using System.Collections.Generic;

Nota:

Agregar código al método Seed es una de las muchas maneras de insertar datos fijos en la base de datos. Una alternativa es agregar código a los métodos Up y Down de cada clase de migración. Los métodos Up y Down contienen código que implementa los cambios de la base de datos. Verá ejemplos de ellos en el tutorial Implementación de una actualización de base de datos.

También puede escribir código que ejecute instrucciones SQL mediante el método Sql. Por ejemplo, si agregaba una columna Presupuesto a la tabla Departamento y quería inicializar todos los presupuestos del departamento a 1000,00 USD como parte de una migración, podría agregar la siguiente línea de código al método Up para esa migración:

Sql("UPDATE Department SET Budget = 1000");

En este ejemplo que se muestra para este tutorial se usa el método AddOrUpdate en el método Seed de la clase Configuration de Migraciones de Code First. Migraciones de Code First llama al método Seed después de cada migración y este método actualiza las filas que ya se han insertado o las inserta si aún no existen. Es posible que el método AddOrUpdate no sea la mejor opción para su escenario. Para más información, consulte Cuidado con el método AddOrUpdate de EF 4.3 en el blog de Julie Lerman.

Presione Ctrl+Mayús+B para compilar el proyecto.

El siguiente paso es crear una clase DbMigration para la migración inicial. Quiere que esta migración cree una nueva base de datos, por lo que debe eliminar la base de datos que ya existe. Las bases de datos de SQL Server Compact se encuentran en los archivos .sdf de la carpeta App_Data. En el Explorador de soluciones, expanda App_Data en el proyecto ContosoUniversity para ver las dos bases de datos de SQL Server Compact, representadas por archivos .sdf.

Haga clic con el botón derecho en el archivo School.sdf y haga clic en Eliminar.

sdf_files_in_Solution_Explorer

En la ventana Consola del Administrador de paquetes, escriba el comando "add-migration Initial" para crear la migración inicial y asígnele el nombre "Initial".

add-migration_command

Las Migraciones de Code First crean otro archivo de clase en la carpeta Migrations y esta clase contiene código que crea el esquema de la base de datos.

En la Consola del Administrador de paquetes, escriba el comando "update-database" para crear la base de datos y ejecutar el método Seed.

update-database_command

(Si recibe un error que indica que ya existe una tabla y no se puede crear, es probable que se deba a que ejecutó la aplicación después de eliminar la base de datos y antes de ejecutar update-database. En ese caso, elimine de nuevo el archivo School.sdf y vuelva a intentarlo con el comando update-database).

Ejecute la aplicación. Ahora la página Estudiantes está vacía, pero la página Instructores contiene instructores. Esto es lo que obtendrá en producción después de implementar la aplicación.

Empty_Students_page

Instructors_page_after_initial_migration

El proyecto ya está listo para implementar la base de datos School.

Creación de una base de datos de pertenencia para la implementación

La aplicación Contoso University usa el sistema de pertenencia a ASP.NET y la autenticación de formularios para autenticar y autorizar a los usuarios. Una de sus páginas solo es accesible para los administradores. Para ver esta página, ejecute la aplicación y seleccione Actualizar créditos en el menú flotante en Cursos. La aplicación muestra la página Inicio de sesión, ya que solo los administradores tienen autorización para usar la página Actualizar créditos.

Log_in_page

Inicie sesión como "admin" con la contraseña "Pas$w0rd" (observe el número cero en lugar de la letra "o" en "w0rd"). Después de iniciar sesión, se muestra la página Actualizar créditos.

Update_Credits_page

Al implementar un sitio por primera vez, es habitual excluir la mayoría o todas las cuentas de usuario que cree para las pruebas. En este caso, implementará una cuenta de administrador y ninguna cuenta de usuario. En lugar de eliminar manualmente las cuentas de prueba, creará una nueva base de datos de pertenencia que solo tiene la cuenta de usuario administrador que necesita en producción.

Nota:

La base de datos de pertenencia almacena un hash de contraseñas de cuenta. Para implementar cuentas de una máquina a otra, debe asegurarse de que las rutinas de hash no generan hash diferentes en el servidor de destino que en el equipo de origen. Generarán los mismos hash al usar Proveedores universales de ASP.NET, siempre y cuando no cambie el algoritmo predeterminado. El algoritmo predeterminado es HMACSHA256 y se especifica en el atributo validation del elemento machineKey en el archivo Web.config.

Las Migraciones de Code First no mantienen la base de datos de pertenencia y no hay ningún inicializador automático que inicializa la base de datos con cuentas de prueba (como ocurre con la base de datos Escuela). Por lo tanto, para mantener los datos de prueba disponibles, realizará una copia de la base de datos de prueba antes de crear uno nuevo.

En el Explorador de soluciones, cambie el nombre del archivo aspnet.sdf de la carpeta App_Data a aspnet-Dev.sdf. (No realice una copia, simplemente cámbiele el nombre; creará una nueva base de datos en un momento).

En el Explorador de soluciones, asegúrese de que el proyecto web (ContosoUniversity, no ContosoUniversity.DAL) está seleccionado. A continuación, en el menú Proyecto, seleccione Configuración de ASP.NET para ejecutar la Herramienta de administración de sitios web (WAT).

Seleccione la pestaña Seguridad .

WAT_Security_tab

Haga clic en Crear o administrar roles y agregue un rol de Administrador.

WAT_Create_New_Role

Vuelva a la pestaña Seguridad, haga clic en Crear usuarioy agregue el usuario "admin" como administrador. Antes de hacer clic en el botón Crear usuario de la página Crear usuario, asegúrese de activar la casilla Administrador. La contraseña usada en este tutorial es "Pas$w0rd" y puede escribir cualquier dirección de correo electrónico.

WAT_Create_User

Cierre el explorador. En el Explorador de soluciones, haga clic en el botón Actualizar para ver el nuevo archivo aspnet.sdf.

New_aspnet.sdf_in_Solution_Explorer

Haga clic con el botón derecho en aspnet.sdf y seleccione Incluir en el proyecto.

Distinguir el desarrollo de las bases de datos de producción

En esta sección, cambiará el nombre de las bases de datos para que las versiones de desarrollo sean School-Dev.sdf y aspnet-Dev.sdf y las versiones de producción son School-Prod.sdf y aspnet-Prod.sdf. Esto no es necesario, pero hacerlo le ayudará a evitar que las versiones de prueba y producción de las bases de datos se confundan.

En el Explorador de soluciones, haga clic en Actualizary expanda la carpeta App_Data para ver la base de datos School que creó anteriormente; haga clic con el botón derecho en ella y seleccione Incluir en el proyecto.

Including_School.sdf_in_project

Cambie el nombre de aspnet.sdf a aspnet-Prod.sdf.

Cambie el nombre de School.sdf a School-Dev.sdf.

Al ejecutar la aplicación en Visual Studio, no desea usar las versiones de -Prod de los archivos de base de datos, quiere usar las versiones de -Dev. Por lo tanto, debe cambiar las cadenas de conexión en el archivo Web.config para que apunten a las versiones de -Dev de las bases de datos. (No ha creado un archivo School-Prod.sdf, pero es correcto porque Code First creará esa base de datos en producción la primera vez que ejecute la aplicación).

Abra el archivo Web.config de la aplicación y busque las cadenas de conexión:

<configuration>
  <!-- Settings -->
  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=|DataDirectory|aspnet.sdf" providerName="System.Data.SqlServerCe.4.0" />
    <add name="SchoolContext" connectionString="Data Source=|DataDirectory|School.sdf" providerName="System.Data.SqlServerCe.4.0" />
  </connectionStrings>
  <!-- Settings -->
</configuration>

Cambie "aspnet.sdf" a "aspnet-Dev.sdf" y cambie "School.sdf" a "School-Dev.sdf":

<configuration>
  <!-- Settings -->
  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=|DataDirectory|aspnet-Dev.sdf" providerName="System.Data.SqlServerCe.4.0" />
    <add name="SchoolContext" connectionString="Data Source=|DataDirectory|School-Dev.sdf" providerName="System.Data.SqlServerCe.4.0" />
  </connectionStrings>
  <!-- Settings -->
</configuration>

El motor de base de datos de SQL Server Compact y ambas bases de datos ya están listas para implementarse. En el siguiente tutorial, configurará transformaciones automáticas de archivos Web.config para los valores que deben ser diferentes en los entornos de desarrollo, prueba y producción. (Entre las opciones de configuración que se deben cambiar se encuentran las cadenas de conexión, pero configurará esos cambios más adelante al crear un perfil de publicación).

Más información

Para obtener más información sobre NuGet, consulte Administración de bibliotecas de proyectos con NuGet y Documentación de NuGet. Si no desea usar NuGet, deberá aprender a analizar un paquete NuGet para determinar qué hace cuando se instala. (Por ejemplo, podría configurar transformaciones de Web.config, configurar scripts de PowerShell para que se ejecuten en tiempo de compilación, etc.) Para obtener más información sobre cómo funciona NuGet, consulte especialmente Crear y publicar un paquete y Transformaciones de código fuente y archivos de configuración.