miércoles, septiembre 26, 2012

ADO.NET Entity Data Model y Data Annotations

Data Annotations permite añadir validaciones al modelo de datos que luego tendrán reflejo en la vista. A continuación mostraré un ejemplo de aplicación hecha con ASP.NET con una única entidad (Team) definida en el modelo de datos y su controlador y vistas creadas por scaffolding (ver post Cómo crear un CRUD (mantenimiento) básico Web utilizando ASP.Net MVC y Entity Framework).

Supongamos que partimos de una entidad Team definida así:

using System.ComponentModel;
using System;
using System.Collections.Generic;  
namespace PruebaEF
{
    public partial class Team
    {
        public int Id { get; set; }        
        public string Name { get; set; }         
        public string City { get; set; }
    }
}

Si creamos el controlador y las vistas mediante scaffolding y ejecutamos el proyecto tendremos (ojo, tendremos que añadir /teams a la URL inicial).


image


image


Si modificamos la entidad añadiendo Data Annotations podemos conseguir algunas validaciones sin necesidad de modificar ni el controlador ni la vista. Veamos el siguiente ejemplo:



using System.ComponentModel;
using
System.ComponentModel.DataAnnotations;
using System;
using
System.Collections.Generic;

namespace
PruebaEF
{
   
   
public partial class Team
    {
        [DisplayName("Identificador")]
       
public int Id { get; set
; }

        [
DisplayName("Nombre del club"
)] 
        [
StringLength
(10)]
       
public string Name { get; set
; }


        [DisplayName("Ciudad")]
       
public string City { get; set
; }
    }
}


El resultado sería el siguiente (sin necesidad de modificar ni el controlador ni las vistas):


image


image


Pero si las entidades las generamos utilizando ADO.NET Entity Data Model tal como se explica en el post anterior (Modelo POCO a partir de ADO.NET Entity Data Model), cada vez que hagamos una modificación desde el diseñador, perderemos las Data Annotations. ¿Y qué podemos hacer al respecto? Tenemos varias opciones aunque ninguna me parece perfecta:



  1. Utilizar el patrón Database-First / Model-First para crear una primera versión del modelo de datos (tal como se explica en el post anterior (Modelo POCO a partir de ADO.NET Entity Data Model) y a partir de ahí eliminar el fichero edmx y pasar a utilizar el patrón Code-First. Siempre podríamos añadir después un elemento de tipo Diagrama de clase para tener una visión gráfica del modelo ;P
  2. Utilizar el generador de código (desde el diseñador) de ADO.NET POCO Entity Generator With Data Annotations. La pega es que sólo sirve para el patrón Database-First y no se pueden añadir o modificar validaciones en el modelo.
  3. Utilizar el patrón Code-First (ver Code-First Development with Entity Framework 4). Si partimos de una BDD existente, podemos utilizar Reverse Engineer Code First (ver Entity Framework Power Tools) para crear las entidades POCO a partir de los objetos de la BDD. Este sistema tampoco me convence porque crea unas clases para el mapeo mediante Fluent-API.
  4. Crear una clase a banda que contenga las anotaciones e indicarlo a la entidad original mediante el atributo MetadataType (ver Validation with the Data Annotation Validators).
  5. Desde el diseñador de ADO.NET Entity Data Model, como generador de código, utilizar ADO.NET Self-Tracking Entity Generator + Data Annotations, que permite añadir validaciones en el diseñador (propiedad Validations de cada una de las entidades). La pega es que esto no genera clases POCO (que es lo que yo estaba buscando).
  6. Utilizar Portable Extensible Metadata (ver Introducing the Portable Extensible Metadata), aunque con esto tampoco conseguiríamos tener clases POCO con anotaciones.

1 comentario:

  1. Hola me gustaria saber como implementar MetadataType desde un archive de recursos ya que si tengo 40 propiedades en un modelo y a cada propiedad le estoy implementado entre 15 y 25 directivas como las mensionadas para validar en la vista eso me daria un monton de suciedad en el codigo y me gustaria tenerlo claro y de facil lectura por ejemplo en mi carpeta Models tengo una carpeta llamada Metadata y la clase NombreModelo + el sufijo MetaData

    ResponderEliminar