lunes, 2 de junio de 2014

[EntityFramework] Agregando propiedades y metadatos a nuestras clases autogeneradas en DB First

Hola amigos, ya que estamos dando por terminada esta serie de post sobre Entity FrameWork no quería dejar a un lado una importante característica que debemos conocer cuando trabajamos con el enfoque Data Base First y que seguro vamos a necesitar en cualquier proyecto en el que usemos este enfoque, y quiero antes que nada plantearles una necesidad para que comprendan con mayor facilidad la utilidad del tema que vamos a tratar en este artículo:

"Recordemos que un principio que debemos tener presente como desarrolladores es, nunca debemos modificar código autogenerado puesto que una vez se vuelva a autogenerar por cualquier motivo, perderemos los cambios que hicimos en el archivo en cuestión"

Bueno, ahora teniendo clara esta premisa, por si aún no se habían topado con algún caso de este tipo, surgen un par de interrogantes cuando trabajamos con Entity Framework DataBase First y son las siguientes:
  1. ¿Cómo puedo yo entonces agregar propiedades a mi entidad de domino directamente que no necesariamente quiero que persistan a mi base de datos?
  2. ¿Cómo puedo yo agregar metadata (Atributtes Data Anottations) adicional a mis entidades de domino?
Pues bien, creo que con estas dos interrogantes ya nos queda claro cuál es la necesidad de usar clases parciales para extender nuestras entidades autogeneradas. Ahora veamos como lo podemos lograr.

En primera instancia vamos a crear un modelo de Entity Framework usando el enfoque DataBase First el cual podemos observar en detalle en este artículo:  Creando nuestro modelo conceptual con DataBase First y como es normal veremos que se autogeneran nuestras entidades con todos sus metadatos, a este código es el que me refiero, no se puede modificar!

En nuestro caso se generó la entidad producto, como vemos a continuación. Si leemos el comentario en el encabezado de la clase veremos que se advierte de las consecuencias de modificarla:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
 
namespace DataBaseFirstDemo.Dominio
{
    using System;
    using System.Collections.Generic;
    
    public partial class Producto
    {
        public Producto()
        {
            this.Categorias = new HashSet<Categoria>();
        }
    
        public string Nombre { getset; }
        public int Codigo { getset; }
    
        public virtual ICollection<Categoria> Categorias { getset; }
    }
}

Ahora bien, que tal si queremos agregar una nueva propiedad a la entidad en la cual podamos obtener el código y el nombre del producto en una sola cadena? para esto creamos una nueva clase parcial llamada producto, la cual debe tener el mismo NameSpace que la clase producto autogenerada, y cabe aclarar algo, el archivo .cs debe tener un nombre diferente a Producto.cs, pero la clase en su interior debe tener el nombre de Producto, para que el FrameWork las trate como una sola. Tal y como vemos a continuación:


Como podemos ver tenemos las dos clases que físicamente son diferentes, es decir en dos archivos diferentes pero lógicamente son una sola, ya que desde la clase que hemos creado podemos ver las propiedades Codigo y Nombre que fueron autogeneradas.

Bastante sencillo, ahora vamos a ver cómo podemos agregar metadata adicional a las propiedades autogeneradas. Ya que como sabemos Entity Framework genera la metadata que obtiene desde la base de datos, como la longitud del campo, constrains y demás.

Lo primero que debemos hacer es crear una clase que puede estar en el interior del archivo Producto.cs que creamos nosotros y la podemos llamar ProductoMetaData, en la cual vamos a replicar todas aquellas propiedades a las cuales queremos agregar metadata adicional, en nuestro caso vamos a replicar la propiedad Nombre, para especificar que es requerida y que solo debe permitir una longitud máxima de 4 caracteres:

using System.ComponentModel.DataAnnotations;
 
namespace DataBaseFirstDemo.Dominio
{
    [MetadataType(typeof(ProductoMetaData))]
    public partial class Producto
    {
        public string InformacionProducto
        {
            get
            {
                return string.Format("{0} - {1}"this.Codigo, this.Nombre);
            }
        }
    }
 
    public class ProductoMetaData
    {
        [RequiredMaxLength(4)]
        public string Nombre { getset; }
    }
}

Y para finalizar debemos indicar que esta clase de metadata va a ser usada por nuestras clase Producto, y lo hacemos decorando nuestras clase con el atributo MetadataType e indicando la clase de metadata que acabamos de crear, tal y como se ve en el fragmento de código anterior.

Bueno amigos eso es todo de esta muestra de cómo agregar propiedades y metadata adicional a nuestras entidades autogenradas en DataBase First, espero les sea de utilidad y de interés. Y no duden en compartirlo.

Saludos, y buena suerte!

4 comentarios:

  1. Muchas gracias mano, muy bien explicado!

    ResponderEliminar
  2. Fantástico!!!
    Gracias me saco de un gran apuro por mi ignorancia. :)

    ResponderEliminar
  3. Cuando intento hacerle un select con la nueva propiedad creada me da un error

    ResponderEliminar