Parte 2: Creación de modelos de dominio

Por Rick Anderson

Descargar el proyecto completado

Agregar modelos

Hay tres maneras de abordar Entity Framework:

  • Primero en la base de datos: empieza con una base de datos y Entity Framework genera el código.
  • Primero en el modelo: empieza con un modelo visual y Entity Framework genera la base de datos y el código.
  • Primero en el código: comienza con el código y Entity Framework genera la base de datos.

Se está usando el enfoque primero en el código, por lo que empezamos definiendo nuestros objetos de dominio como POCO (objetos CLR sin formato antiguos). Con el enfoque primero en el código, los objetos de dominio no necesitan ningún código adicional para admitir la capa de base de datos, como transacciones o persistencia. (En concreto, no es necesario heredar de la clase EntityObject). Todavía puede usar anotaciones de datos para controlar cómo Entity Framework crea el esquema de la base de datos.

Dado que los POCOs no contienen propiedades adicionales que describen estado de la base de datos, se pueden serializar fácilmente en JSON o XML. Sin embargo, eso no significa que siempre debe exponer los modelos de Entity Framework directamente a los clientes, como veremos más adelante en el tutorial.

Crearemos los siguientes POCO:

  • Producto
  • compra
  • OrderDetail

Para crear cada clase, haga clic con el botón derecho en la carpeta Models de Explorador de soluciones. En el menú contextual, seleccione Agregar y, a continuación, seleccione Clase.

Screenshot of the Solutions Explorer menu for the Models folder. The Add menu is open and the Class option is highlighted.

Agregue una clase Product con la siguiente implementación:

namespace ProductStore.Models
{
    using System.ComponentModel.DataAnnotations;

    public class Product
    {
        [ScaffoldColumn(false)]
        public int Id { get; set; }
        [Required]
        public string Name { get; set; }
        public decimal Price { get; set; }
        public decimal ActualCost { get; set; }
    }
}

Por convención, Entity Framework usa la propiedad Id como clave principal y la asigna a una columna de identidad de la tabla de base de datos. Al crear una nueva instancia Product, no establecerá un valor para Id, ya que la base de datos genera el valor.

El atributo ScaffoldColumn indica a ASP.NET MVC omitir la propiedad Id al generar un formulario del editor. El atributo Obligatorio se usa para validar el modelo. Especifica que la propiedad Name debe ser una cadena no vacía.

Agregar la clase Order:

namespace ProductStore.Models
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;

    public class Order
    {
        public int Id { get; set; }
        [Required]
        public string Customer { get; set; }

        // Navigation property
        public  ICollection<OrderDetail> OrderDetails { get; set; }
    }
}

Agregar la clase OrderDetail:

namespace ProductStore.Models
{
    public class OrderDetail
    {
        public int Id { get; set; }
        public int Quantity { get; set; }
        public int OrderId { get; set; }
        public int ProductId { get; set; }

        // Navigation properties
        public Product Product { get; set; }
        public Order Order { get; set; }
    }
}

Relaciones de claves externas

Un pedido contiene muchos detalles de pedido y cada detalle del pedido hace referencia a un único producto. Para representar estas relaciones, la clase OrderDetail define las propiedades denominadas OrderId y ProductId. Entity Framework deducirá que estas propiedades representan claves externas y agregarán restricciones de clave externa a la base de datos.

Screenshot of Visual Studio menus for the Orders, Products, and OrderDetails classes.

Las clases Order y OrderDetail también incluyen propiedades de "navegación", que contienen referencias a los objetos relacionados. Dado un pedido, puede navegar a los productos en el pedido siguiendo las propiedades de navegación.

Compilar el proyecto ahora. Entity Framework usa la reflexión para detectar las propiedades de los modelos, por lo que requiere un ensamblado compilado para crear el esquema de la base de datos.

Configurar los formateadores de tipo multimedia

Un formateador de tipo multimedia es un objeto que serializa los datos cuando la API web escribe el cuerpo de la respuesta HTTP. Los formateadores integrados admiten la salida JSON y XML. De forma predeterminada, ambos formateadores serializan todos los objetos por valor.

La serialización por valor crea un problema si un gráfico de objetos contiene referencias circulares. Ese es exactamente el caso de las clases Order y OrderDetail, ya que cada una contiene una referencia a la otra. El formateador seguirá las referencias, escribirá cada objeto por valor y irá en círculos. Por lo tanto, es necesario cambiar el comportamiento predeterminado.

En el Explorador de soluciones, expanda la carpeta App_Start y abra el archivo denominado WebApiConfig.cs. Agregue el siguiente código a la clase WebApiConfig:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        // New code:
        var json = config.Formatters.JsonFormatter;
        json.SerializerSettings.PreserveReferencesHandling =
            Newtonsoft.Json.PreserveReferencesHandling.Objects;

        config.Formatters.Remove(config.Formatters.XmlFormatter);
    }
}

Este código establece el formateador JSON para conservar las referencias de objeto y quita completamente el formateador XML de la canalización. (Puede configurar el formateador XML para conservar las referencias de objeto, pero es un poco más de trabajo y solo necesitamos JSON para esta aplicación. Para obtener más información, vea Control de referencias de objetos circulares).