Compartir a través de


Crear clases de modelo con LINQ to SQL (C#)

por Microsoft

Descargar PDF

El objetivo de este tutorial es explicar un método para crear clases de modelo para una aplicación ASP.NET MVC. En este tutorial, aprenderá a crear clases de modelo y a realizar el acceso a la base de datos aprovechando Microsoft LINQ to SQL.

El objetivo de este tutorial es explicar un método para crear clases de modelo para una aplicación ASP.NET MVC. En este tutorial, aprenderá a crear clases de modelo y a realizar el acceso a la base de datos aprovechando Microsoft LINQ to SQL.

En este tutorial, se crea una aplicación básica de base de datos de películas. Comenzamos creando la aplicación de base de datos de películas de la forma más rápida y sencilla posible. Realizamos todo el acceso a los datos directamente desde nuestras acciones del controlador.

A continuación, aprenderemos a usar el patrón Repository. El uso del patrón Repository requiere un poco más de trabajo. Sin embargo, la ventaja de adoptar este patrón es que permite compilar aplicaciones adaptables al cambio y que se pueden probar fácilmente.

¿Qué es una clase Model?

Un modelo MVC contiene toda la lógica de la aplicación que no está incluida en una vista o un controlador. En concreto, contiene toda la lógica de acceso a datos y de negocio de la aplicación.

Para implementar la lógica de acceso a datos puede usar una variedad de tecnologías diferentes. Por ejemplo, puede crear las clases de acceso a datos mediante las clases Microsoft Entity Framework, NHibernate, Subsonic o ADO.NET.

En este tutorial, usaremos LINQ to SQL para consultar y actualizar la base de datos. LINQ to SQL proporciona un método muy fácil de interactuar con una base de datos de Microsoft SQL Server. Sin embargo, es importante comprender que el marco ASP.NET MVC no está vinculado a LINQ to SQL de ninguna manera. ASP.NET MVC es compatible con cualquier tecnología de acceso a datos.

Creación de una base de datos de películas

En este tutorial, para ilustrar cómo se crean clases de modelo, creamos una sencilla aplicación de base de datos de películas. El primer paso consiste en crear una nueva base de datos. Haga clic con el botón derecho en la carpeta App_Data de la ventana del Explorador de soluciones y seleccione la opción de menú Agregar, Nuevo elemento. Seleccione la plantilla Base de datos SQL Server, asígnele el nombre MoviesDB.mdf y haga clic en el botón Agregar (vea la figura 1).

Adding a new SQL Server Database

Figura 01: Incorporación de una nueva base de datos de SQL Server (haga clic para ver la imagen a tamaño completo)

Después de crear la nueva base de datos, haga doble clic en el archivo MoviesDB.mdf en la carpeta App_Data para abrirla. Al hacer doble clic en el archivo MoviesDB.mdf, se abre la ventana Explorador de servidores (consulte la figura 2).

La ventana Explorador de servidores se denomina ventana Explorador de bases de datos cuando se usa Visual Web Developer.

Screenshot of the Server Explorer window, which shows that the Tables folder is highlighted in the folder hierarchy.

Figura 02: Uso de la ventana Explorador de servidores (haga clic para ver la imagen a tamaño completo)

Necesitamos agregar una tabla a nuestra base de datos que represente nuestras películas. Haga clic con el botón derecho en la carpeta Tablas y seleccione la opción de menú Agregar nueva tabla. Al seleccionar esta opción de menú, se abre el Diseñador de tablas (consulte la figura 3).

Screenshot of the Microsoft Visual Studio window, which shows the Table Designer feature.

Figura 03: Diseñador de tablas (haga clic para ver la imagen a tamaño completo)

Es necesario agregar las columnas siguientes a la tabla de base de datos:

Nombre de la columna Tipo de datos Permitir valores NULL
Identificador Int False
Título Nvarchar(200) False
Director Nvarchar(50) False

Debe hacer dos cosas especiales en la columna Id. En primer lugar, marque la columna Id como columna de clave principal seleccionando la columna en el Diseñador de tablas y haciendo clic en el icono de una clave. LINQ to SQL necesita que se especifiquen las columnas de clave principal al realizar inserciones o actualizaciones en la base de datos.

A continuación, marque la columna Id como columna Identity mediante la asignación del valor Sí a la propiedad Is Identity (consulte la figura 3). Una columna Identity es la que se asigna automáticamente a un nuevo número cada vez que se agrega una nueva fila de datos a una tabla.

Creación de clases LINQ to SQL

Nuestro modelo MVC contendrá clases LINQ to SQL que representan la tabla de base de datos tblMovie. La manera más fácil de crear estas clases LINQ to SQL es hacer clic con el botón derecho en la carpeta Models, seleccionar Agregar, Nuevo elemento, seleccionar la plantilla LINQ to SQL Classes, asignarle el nombre Movie.dbml y hacer clic en el botón Agregar (consulte la figura 4).

Creating LINQ to SQL classes

Figura 04: Creación de clases LINQ to SQL (haga clic para ver la imagen a tamaño completo)

Inmediatamente después de crear las clases Movie de LINQ to SQL, aparecerá Object Relational Designer. Puede arrastrar las tablas de la base de datos desde la ventana del Explorador de servidores a Object Relational Designer para crear clases LINQ to SQL que representen tablas concretas de la base de datos. Tenemos que agregar la tabla de base de datos tblMovie en Object Relational Designer (ver figura 5).

Using the Object Relational Designer

Figura 05: Uso de Object Relational Designer (haga clic para ver la imagen a tamaño completo)

De manera predeterminada, Object Relational Designer crea una clase con el mismo nombre que la tabla de la base de datos que arrastre al Diseñador. Sin embargo, no queremos llamar a nuestra clase tblMovie. Por lo tanto, haga clic en el nombre de la clase en el Diseñador y cambie el nombre de la clase a Movie.

Por último, recuerde hacer clic en el botón Guardar (la imagen del disquete) para guardar la plantilla LINQ to SQL Classes. De lo contrario, Object Relational Designer no generará las clases LINQ to SQL.

Uso de LINQ to SQL en una acción del controlador

Ahora que tenemos nuestras clases de LINQ to SQL, podemos usarlas para recuperar datos de la base de datos. En esta sección, aprenderá a usar las clases LINQ to SQL directamente dentro de una acción de controlador. Mostraremos la lista de películas de la tabla de base de datos tblMovies en una vista MVC.

En primer lugar, es necesario modificar la clase HomeController. Esta clase se encuentra en la carpeta Controllers de la aplicación. Modifique la clase para que tenga el aspecto de la clase de la lista 1.

Lista 1: Controllers\HomeController.cs

using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
     [HandleError]
     public class HomeController : Controller
     {
          public ActionResult Index()
          {
               var dataContext = new MovieDataContext();
               var movies = from m in dataContext.Movies
                    select m;
               return View(movies);
          }
     }
}

La acción Index() de la descripción 1 usa una clase LINQ to SQL DataContext (MovieDataContext) para representar la base de datos MoviesDB. La clase MoveDataContext fue generada por Object Relational Designer de Visual Studio.

Se realiza una consulta LINQ en DataContext para recuperar todas las películas de la tabla de base de datos tblMovies. La lista de películas se asigna a una variable local denominada movies. Por último, la lista de películas se pasa a la vista mediante los datos de la vista.

Para mostrar las películas, es necesario modificar la vista Index. La vista Index se encuentra en la carpeta Views\Home\. Actualice la vista Index para que tenga un aspecto similar a la vista de la lista 2.

Lista 2: Views\Home\Index.aspx

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">

     <ul>
          <% foreach (Movie m in (IEnumerable)ViewData.Model)

          { %>
               <li> <%= m.Title %> </li>
          <% } %>
     </ul>
</asp:Content>

Observe que la vista Index modificada incluye una directiva <%@ import namespace %> en la parte superior. Esta directiva importa MvcApplication1.Models namespace. Necesitamos este espacio de nombres para trabajar con las clases model (en particular, la clase Movie) en la vista.

La vista de la lista 2 contiene un bucle foreach que recorre en iteración todos los elementos representados por la propiedad ViewData.Model. El valor de la propiedad Title se muestra para cada movie.

Observe que el valor de la propiedad ViewData.Model se convierte en un IEnumerable. Esto es necesario para recorrer en bucle el contenido de ViewData.Model. Otra opción aquí es crear una viewfuertemente tipada. Cuando se crea una view fuertemente tipada, se convierte la propiedad ViewData.Model en un tipo determinado en la clase de código subyacente de una vista.

Si ejecuta la aplicación después de modificar la clase HomeController y la vista Index, obtendrá una página en blanco. Obtendrá una página en blanco porque no hay ningún registro de película en la tabla de base de datos tblMovies.

Para agregar registros a la tabla de base de datos tblMovies, haga clic con el botón derecho en la tabla de base de datos tblMovies en la ventana Explorador de servidores (ventana Explorador de bases de datos en Visual Web Developer) y seleccione la opción de menú Mostrar datos de tabla. Puede insertar registros de movie mediante la cuadrícula que aparece (consulte la figura 6).

Inserting movies

Figura 06: Inserción de películas (haga clic para ver la imagen a tamaño completo)

Después de agregar algunos registros de base de datos a la tabla tblMovies y ejecutar la aplicación, verá la página de la figura 7. Todos los registros de la base de datos de películas se muestran en una lista con viñetas.

Displaying movies with the Index view

Figura 07: Visualización de las películas con la vista Index (haga clic para ver la imagen a tamaño completo)

Uso del patrón Repository

En la sección anterior, usamos clases LINQ to SQL directamente dentro de una acción de controlador. Usamos la clase MovieDataContext directamente desde la acción del controlador Index(). No hay nada malo en hacerlo en el caso de una aplicación sencilla. Sin embargo, trabajar directamente con LINQ to SQL en una clase de controlador implica problemas al compilar una aplicación más compleja.

El uso de LINQ to SQL en una clase de controlador dificulta el cambio de tecnologías de acceso a datos en el futuro. Por ejemplo, puede decidir cambiar de Microsoft LINQ to SQL a Microsoft Entity Framework como tecnología de acceso a los datos. En ese caso, tendría que volver a escribir todos los controladores que tengan acceso a la base de datos dentro de la aplicación.

El uso de LINQ to SQL dentro de una clase de controlador también dificulta la compilación de pruebas unitarias para la aplicación. Normalmente, no se quiere interactuar con una base de datos al realizar pruebas unitarias. Las pruebas unitarias sirven para probar la lógica de la aplicación y no el servidor de bases de datos.

Para compilar una aplicación de MVC más adaptable al cambio futuro y que se pueda probar más fácilmente, considere el patrón Repository. Al usar el patrón Repository, se crea una clase de repositorio independiente que contiene toda la lógica de acceso a la base de datos.

Al crear la clase Repository, se crea una interfaz que representa todos los métodos que esta usa. Dentro de los controladores, escribirá el código en la interfaz en lugar de en el repositorio. De este modo, puede implementar el repositorio mediante diferentes tecnologías de acceso a datos en el futuro.

La interfaz de la lista 3 se denomina IMovieRepository y representa un único método denominado ListAll().

Lista 3: Models\IMovieRepository.cs

using System.Collections.Generic;
namespace MvcApplication1.Models
{
     public interface IMovieRepository
     {
          IList<Movie> ListAll();
     }
}

La clase de repositorio de la lista 4 implementa la interfaz IMovieRepository. Observe que contiene un método denominado ListAll() que corresponde al método que requiere la interfaz IMovieRepository.

Lista 4: Models\MovieRepository.cs

using System.Collections.Generic;
using System.Linq;

namespace MvcApplication1.Models
{
     public class MovieRepository : IMovieRepository
     {
          private MovieDataContext _dataContext;

          public MovieRepository()
          {
                _dataContext = new MovieDataContext();
          }

          #region IMovieRepository Members

          public IList<Movie> ListAll()
          {
               var movies = from m in _dataContext.Movies
                    select m;
               return movies.ToList();
          }

          #endregion
     }
}

Por último, la clase MoviesController de la lista 5 usa el patrón Repository. Ya no usa clases LINQ to SQL directamente.

Lista 5: Controllers\MoviesController.cs

using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
     public class MoviesController : Controller
     {
          private IMovieRepository _repository;

          public MoviesController() : this(new MovieRepository())
          {
          }

          public MoviesController(IMovieRepository repository)
          {
               _repository = repository;
          }

          public ActionResult Index()
          {
               return View(_repository.ListAll());
          }
     }
}

Observe que la clase MoviesController de la lista 5 tiene dos constructores. Al primer constructor, sin parámetros, se le llama cuando se ejecuta la aplicación. Este constructor crea una instancia de la clase MovieRepository y la pasa al segundo constructor.

El segundo constructor tiene un único parámetro: IMovieRepository. Este constructor simplemente asigna el valor del parámetro a un campo de nivel de clase denominado _repository.

La clase MoviesController aprovecha un patrón de diseño de software denominado patrón de inserción de dependencias. En concreto, usa algo denominado Inserción de dependencias de constructor. Para más información sobre este patrón, lea el siguiente artículo de Martin Fowler:

http://martinfowler.com/articles/injection.html

Observe que todo el código de la clase MoviesController (con la excepción del primer constructor) interactúa con la interfaz IMovieRepository en lugar de la clase MovieRepository real. El código interactúa con una interfaz abstracta en lugar de una implementación concreta de la interfaz.

Si desea modificar la tecnología de acceso a datos que usa la aplicación, simplemente implemente la interfaz IMovieRepository con una clase que use la tecnología alternativa de acceso a bases de datos. Por ejemplo, podría crear una clase EntityFrameworkMovieRepository o una clase SubSonicMovieRepository. Dado que la clase de controlador está programada en la interfaz, puede pasar una nueva implementación de IMovieRepository a la clase de controlador y la clase seguiría funcionando.

Además, si desea probar la clase MoviesController, puede pasar una clase de repositorio de películas falsa a HomeController. Puede implementar la clase IMovieRepository con una clase que realmente no tiene acceso a la base de datos, pero contiene todos los métodos necesarios de la interfaz IMovieRepository. De este modo, realiza pruebas unitarias de la clase MoviesController sin acceder a una base de datos real.

Resumen

El objetivo de este tutorial era demostrar cómo se crean clases de modelo de MVC aprovechando Microsoft LINQ to SQL. Hemos examinado dos estrategias para mostrar datos de base de datos en una aplicación ASP.NET MVC. En primer lugar, creamos clases LINQ to SQL y usamos las clases directamente dentro de una acción de controlador. El uso de clases LINQ to SQL dentro de un controlador permite mostrar datos de base de datos de forma rápida y sencilla en una aplicación MVC.

A continuación, hemos explorado una ruta de acceso un poco más difícil, pero definitivamente más virtuosa para mostrar los datos de la base de datos. Aprovechamos el patrón Repository y colocamos toda la lógica de acceso a la base de datos en una clase de repositorio independiente. En nuestro controlador, hemos escrito todo el código en una interfaz en lugar de en una clase concreta. La ventaja del patrón Repository es que nos permite cambiar fácilmente las tecnologías de acceso a bases de datos en el futuro y probar fácilmente nuestras clases de controlador.