lunes, 14 de noviembre de 2011

Asociaciones en Entity Framework

Siguiendo con el modelado del dominio en Entity Framework y bajo la opción Database First, en este post hablaremos sobre los distintos tipos de asociaciones disponibles.

Los tipos de asociaciones disponibles en Entity Framework son:

  • Asociaciones independientes
  • Asociaciones de clave externa

Asumiendo que utilizamos el asistente para actualizar el modelo desde la base de datos: Si activamos la opción “Incluir columnas de clave externa en el modelo” (por defecto está activada), las asociaciones que se crearán serán del tipo “Asociación de clave externa”. Por otro lado, sino activamos esta opción se crearán asociaciones de tipo independiente (esto claro, siempre y cuando haya definidas relaciones en nuestra base de datos).

Las asociaciones de clave externa se basan en la restricción referencial y no permiten ningún tipo de mapeo en la asociación. Además, este tipo de asociaciones también incluyen las columnas de clave externa como propiedades en la entidad secundaria en la relación, con lo que podemos trabajar con las entidades asociadas tanto a nivel de propiedad como a nivel de objeto (por ejemplo, podemos asignar el cliente de un pedido con un simple Pedido.IdCliente = 5, en vez de tener que asignar un objeto de tipo Cliente a la propiedad Pedido.Cliente).

Por otro lado, las asociaciones independientes requieren un mapeo entre las propiedades de entidades del modelo y campos de las tablas del modelo relacional.

Por ejemplo, si partimos del siguiente modelo relacional:

clip_image001

Si activamos la opción “Incluir columnas de clave externa en el modelo”, nuestro modelo conceptual quedará como sigue (fijarse que la columna IdCliente en Pedidos está presente):

clip_image002

Si vemos los detalles de la asignación de la asociación creada, podemos ver como EF nos indica que “No están permitidas las asignaciones para una asociación de claves externas expuestas.”

clip_image004

Pero entonces ¿Cómo sabe EF cuál es la relación entre ambas entidades? Lo sabe a partir de la propiedad “Restricción referencial” del objeto asociación.

clip_image005

clip_image006

Por el contrario, si no activamos la opción “Incluir columnas de clave externa en el modelo”, las asociaciones que se crearán serán del tipo independiente.

clip_image007

En este tipo de asociaciones, las claves externas de la entidad secundaria no son expuestas como propiedades (ver que IdCliente en Pedidos no tiene ninguna asignación).

clip_image009

A cambio, ahora sí tenemos el detalle del mapeo de la asignación a campos y propiedades concretas a la entidad principal y secundaria en la asociación.

clip_image011

Cabe mencionar que podemos crear cualquier tipo de asociación (tanto de clave externa como independiente) con independencia de si están o no creadas las restricciones foreign key en el modelo relacional. Por contra, si existe la relación en base de datos, ya sea del tipo que sea siempre habrá que crear una asociación en el modelo.

Yo personalmente, me inclino siempre por las asociaciones de tipo de clave externa. A este respecto cabe mencionar que, si trabajas con una base de datos “legacy” (esto es, que no tiene relaciones) es importante que sepas que la navegación por propiedades de la asociación en una consulta LINQ generará LEFT JOIN en vez de INNER JOIN. En mi caso, siempre opto por crear las relaciones (aunque no exijan integridad referencial) y así por lo menos asegurar que se lanzará un INNER JOIN.

Imagina por ejemplo, las siguientes tablas y la siguiente consulta LINQ:

image

var q = from p in context.Pedidos select new { p.PedidoId, p.Clientes.Nombre };

En el modelo tenemos creada una relación, pero dependiendo de si existe o no una FK en la base de datos, la consulta LINQ generará un LEFT o un INNER JOIN.

  • Sin FK creada en BD, será un LEFT JOIN.
  • Con FK creada en BD (con independencia de si exige o no integridad referencial), será un INNER JOIN.

Un saludo!

1 comentario:

  1. Buenas...tengo un problema con el asignamiento de valores cuando tengo una relacion independiente hecha, apesar q los valores de foreign key (los Primary key de la tabla padre) de la tabla hija no existen, me permite llenar la tabla sin ninguna restriccion. Me deberia mostrar un aviso en el que los foreign key asignados, no existen dentro del entity framework. Se podra hacer esta regla para el EF 5.0?

    ResponderEliminar