viernes, 7 de febrero de 2014

Tipos complejos o value objects con Code First

Cuando diseñamos nuestro modelo conceptual (me atrevería a decir nuestro modelo de dominio en escenarios DDD), surge la necesidad de diferenciar entre entidades y value objects.

Si hemos optado por Database First, la operación es muy sencilla y se realiza en apenas un par de clicks en el diseñador de EF.

clip_image002

 

Si por el contrario estamos usando Code First la cosa cambia. Para que se percate de que queremos un value object tenemos que seguir ciertas convenciones o bien instruir a EF con DataAnnotations o FluentAPI.

 

Las convenciones que sigue Code First para descubrir un tipo complejo (así lo llama en terminología EF) son las siguientes:

  • El tipo no puede tener una clave.
  • El tipo sólo puede contener propiedades de tipos básicos.
  • El tipo sólo puede ser una referencia en una propiedad de navegación (es decir, no puede estar en un extremo “varios”).

 

Partiendo de una sencilla clase Cliente y una Dirección, veremos cómo crear el tipo complejo y salvar algunos escollos si se produjeran.

 

class Cliente

{

    public int ClienteId { get; set; }

    public virtual Direccion Direccion { get; set; }

}

 

class Direccion

{

    public string Provincia { get; set; }

    public string CodigoPostal { get; set; }

    public string Calle { get; set; }       

}

Se vuelca en la base de datos de la siguiente forma:

clip_image003

Como veras la convención de nombrado de los campos en la bd es NombrePropiedadClasePadre_NombrePropiedad.

Si hacemos algo que incumple las reglas por las que Code First descubre un tipo complejo, tendremos que utilizar DataAnnotations o FluentAPI para “corregir” a Code First.

class Direccion

{

    public int DireccionId { get; set; }

    public string Provincia { get; set; }

    public string CodigoPostal { get; set; }

    public string Calle { get; set; }

}

clip_image004

¡Oye! Eso no lo que queríamos… ¡Claro!, encontró una clave en Direccion (DireccionId) y creo una entidad y no un value object.

Actualización: Me corrige vía twitter Nicolás Herrara y me dice que si Dirección ahora tiene Id, ya tiene identidad luego ya no es un value object. ¡Correcto! Asumo que es un ejemplo bastante rebuscado a la par que desafortunado, pero lo que quería mostrar era que con [ComplexType] puedes prevalecer sobre las convenciones de Code First. ¡Gracias Nicolás!

Para solucionarlo tenemos 2 opciones bien sencillas:

Con DataAnnotations:

    [ComplexType]

    class Direccion

Con FluentApi:

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

    modelBuilder.ComplexType<Direccion>();

}

¡Ahora sí!

clip_image005

Un saludo!

No hay comentarios:

Publicar un comentario