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.
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:
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; }
}
¡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í!
Un saludo!
No hay comentarios:
Publicar un comentario