viernes, 29 de julio de 2011

Entity Framework: Actualizar modelo desde base de datos


El asistente que aparece cuando pulsamos la opción ‘Actualizar modelo desde base de datos’ es la manera que tenemos en Entity Framework de actualizar el modelo a partir de los cambios realizados en la base de datos subyacente.

Después de realizar pruebas sobre qué cambios refleja automáticamente y cuáles no, mi conclusión y opinión es que sólo lleva a cabo de forma automática aquellas tareas que son seguras y no romperán la compatibilidad con nuestro código. Es decir, al fin y al cabo, EF no pretende ser más que un mapeador de modelos físicos (bases de datos) y modelos conceptuales (modelos del dominio). La relación 1:1 entre el modelo físico y el modelo conceptual podría o no existir en función del modelo que hayamos diseñado. Siendo así, EF no quiere meterse en problemas y la mayoría de decisiones que hay tomar cuando se detectan cambios en el modelo físico, recaen en manos del programador.

A continuación se exponen algunas de las situaciones que normalmente sucederán en una base de datos en la que se apoya un desarrollo.

Se agrega una nueva tabla

Se debe seleccionar la nueva tabla en la pestaña ‘Agregar’ del ‘Asistente para actualizar’.

Se agrega una nueva columna en una tabla

Se agrega automáticamente una nueva propiedad mapeada a la nueva columna en la entidad.

Hay que fijarse que la nueva propiedad se agrega como última propiedad de la entidad. Además, no podemos ordenar las propiedades en la entidad desde el diseñador ni desde la ventana ‘Detalles de la asignación’ (en VS2012 ya sí, tenemos menú contextual – Mover propiedades). Por supuesto, tampoco funciona cortar y pegar porque cuando se pega, las propiedades también se anexan al final de la entidad. Si por algún motivo, que las propiedades de la entidad no estén ordenadas nos quita el sueño, la única solución parece ser editar manualmente el fichero edmx y en concreto la sección CSDL y la ordenación de elementos Property dentro del elemento EntityType correspondiente.

En general, no se recomienda editar manualmente el fichero edmx, pero hay situaciones en las que no hay más remedio (no así en ésta última, que al fin y al cabo, es sólo un motivo estético). En cualquier caso, si editamos el fichero edmx, podría darse la situación de que el diseñador visual no funcionara y entonces y a partir de ese momento, ya todos los cambios tendríamos que realizarlos a mano sobre el fichero edmx.

Se agrega una nueva tabla sin PK

En EF todas las entidades tienen que tener una clave definida, así que si durante el proceso de actualización EF se encuentra una tabla sin PK, determinará que todas las columnas que no acepten nulos serán la clave primaria en nuestra entidad. Puedes visitar el siguiente enlace donde se habla de ello.

Si desde el diseñador y para la propiedad ‘Clave de entidad’, la establecemos a False para todas las propiedades de un entidad, obtendremos el siguiente error:

image

Por ello, parece que es innegociable que una entidad tenga definida una clave.

Se elimina una columna de una tabla

La propiedad asociada en la entidad no se elimina y tenemos el error ‘La propiedad <NombrePropiedad> no está asignada’. Siendo así, hay que eliminar manualmente la propiedad de la entidad.

Se cambia el nombre de una columna en una tabla

Esto provoca que se agregue una nueva propiedad a la entidad con el nuevo nombre de la columna. Por otro lado, la antigua propiedad de la entidad que estaba mapeada al nombre antiguo aún persiste y tenemos el error ‘La propiedad <NombrePropiedad> no está asignada’. Al igual que en el caso anterior, hay que eliminar manualmente la propiedad de la entidad.

Se cambia la PK de una tabla

El modelo de base de datos (SSDL) sí refleja el cambio, pero el modelo conceptual (CSDL) y el mapeo (CDL) no reflejan ningún cambio. Siendo así, la entidad aún tiene como clave principal el mapeo original y este cambio tendrá que ser realizado de forma manual en el modelo.

En cualquier caso, EF nos informa de ello con este error ‘Todas las propiedades (<Entidad>.<AntiguoCampoPK>) de EntitySet <Entidad> se deben asignar a las propiedades de clave (<Entidad>.<NuevoCampoPK>) de la tabla <Entidad>.’.

Se elimina una tabla

Esto conlleva que se elimina su información en la sección SSDL (Storage) y MSL (Mapping) pero no se elimina la entidad (sigue estando en la sección CSDL). Eliminar la entidad es responsabilidad nuestra y tendrá que ser realizado de forma manual.

Se cambia el nombre de una tabla

En realidad esto se traduce en que la pestaña ‘Eliminar’ del ‘Asistente para actualizar’, eliminará la tabla con el nombre antiguo (aplicando la misma lógica que el punto anterior ‘Se elimina una tabla’) y que además deberíamos seleccionar la nueva tabla (perdón, quise decir misma tabla con distinto nombre) en la pestaña ‘Agregar’. Finalmente, bien eliminamos la entidad que estaba mapeada al antiguo nombre de tabla o bien volvemos a mapear esta entidad a la nueva tabla.

Se cambia el tipo de una columna o si admite o no nulos.

En ambos casos, la entidad no refleja cambio alguno y tendremos que hacer estos cambios de forma manual.

La verdad es que tenemos que estar bastante al tanto de todos los cambios y llevar al día el modelo relacional con el modelo conceptual. Nada mas, sólo que espero poco a poco ir publicando posts relacionados con Entity Framework porque eso será señal inequívoca de que avanzo en su estudio y uso en mis desarrollos.

Un saludo!

4 comentarios:

  1. Una de las cosas que me lleva de cabeza es cuando quitas una columna de una entidad y luego al guardar el objeto de la base de datos sigue creyendo que esa columna existe y da un sqlexception. No sé exactamente en qué contexto ocurre eso pero ocurre :(

    ResponderEliminar
  2. Yo he añadido una tabla nueva al modelo que consta de tres primary keys y a pesar de que aparece en el edmx relacionada perfectamente con el resto de tablas, me da el siguiente error:
    Error 4 No se puede encontrar el tipo o el nombre de espacio de nombres 'CategoryOfferExternalPath' (¿falta una directiva using o una referencia de ensamblado?) O:\proyectos\Kvantex_V1\Import\EntityFramework\Models\ProductModel\ProductDBModel.Context.cs 90 105 Repository.EntityFramework

    Es como si no pudiera actualizar el entity framework... no sé, pero ya me lo ha hecho en otras ocasiones y he tenido que borrar el modelo y volver a crearlo, sin embargo esta vez no puedo borrar el modelo!!, alguna sugerencia???

    ResponderEliminar
    Respuestas
    1. Uff, sin más datos no te puedo ayudar como quisiera. Yo personalmente creo que el diseñador visual de EF "NO" es una gran herramienta. Hace muchos extraños. Sobre todo te da errores que a veces no están todo lo relacionados con él como debieran. Es decir, ¿Qué es CategoryOfferExternalPath? ¿Es una entidad de tu modelo? Lo digo porque a veces no puede generar las clases de entidad porque hay un fallo en los .tt (si por ejemplo están generando las entidades en un ensamblado distinto) y como el .tt del contexto depende de las entidades, entonces falla el contexto. Por ejemplo te puedo lanzar 10 excepciones en la ventana de errores, solucionar uno y solucionar entonces del tirón los 10. Es muy "escandaloso", como encuentra algo mal parece que se va a acabar el mundo, luego lo solucionas... y voila! todo solucionado.
      Si puedes aportar algún dato más estaré encantado de ayudarte.
      Un saludo!

      Eliminar