El EF es una de las herramientas más poderosas con las que he tenido que trabajar usando tecnologías de Microsoft, sus alcances son muy interesantes, nos ofrece innumerables funcionalidades y mecanismos; a tal grado que cada día podemos descubrir algo nuevo, algo que no sabíamos, pero también puede ser un dolor de cabeza cuando no sabemos por dónde empezar.
La mayor parte del tiempo, damos por sentado que la herramienta hará todo por nosotros y pocos somos lo que nos interesamos en saber como lo hace.
Ayer se presento un problema en el proyecto en que estamos trabajando, mismo que fue solucionado después de investigar y leer sobre el tema.
Problema
En el proyecto se tiene una relación Master-Detail, en esta relación es necesario agregar entidades al detalle, mismas que ya existen en la base de datos, sin embargo, es necesario validar la información antes de guardar, ya que si no cumple con las reglas de validación no se debe guardar.
En aquellos casos en los que la información no cumple, deben permitirnos repetir el proceso una vez que los datos se actualicen; pero al momento de repetirlo (aparentemente) y realizar la validación por segunda vez, resulta que el detalle que agregamos la primera vez nunca se descargó ni tampoco volvió a cargar los datos originales desde la base de datos, tal parece que existiera algún cache o que se conservan en memoria, esto provoca que se sigan agregando los mismos datos de forma repetida, o que a la información que no cumplió las reglas (que aun esta en nuestro data context), se le puedan agregar nuevos datos que se almacenaran cuando la entidad se logre grabar, siempre y cuando no haya reglas en la base de datos que estén siendo violadas por la información que no debería salvarse.
Tal parece que con eliminar los datos que no cumplieron las reglas, se solucionaría el problema, sin embargo esto tampoco puede ser, ya que a estas alturas no sabe que se tenía originalmente.
Análisis
El problema podría solucionarse si pudiéramos revertir los cambios o si pudiéramos volver a cargar la información original.
El EF lleva un seguimiento de los cambios realizados en memoria, por ese motivo cuando se recuperan de nuevo los registros, el comportamiento default del EF descarta aquellos registros que ya hayan sido cargados previamente, para evitar que los cambios hasta el momento realizados, se pudieran perder; este mecanismo está basado en únicamente en las EntityKeys ( o sea los identificadores de la tabla), debido a esto, cuando se recuperan los datos, solo se verifica si los EntityKeys (id) existen, si existen, entonces la información cargada, no se modificara.
El comportamiento default es correcto, si no queremos sobre escribir los cambios hechos; pero, que pasa si queremos sobre escribirlos?
Solución
Para sobre escribir los cambios es necesario cambiar el comportamiento del objectContext. Sin embargo esto debe realizarse con mucho cuidado, ya que si no lo tenemos en cuanta, esto podría afectar a toda la aplicación.
Para no afectar a toda la aplicación, lo recomendable es que se modifique el comportamiento del objectContext, únicamente en donde se requiera.
La actualización puedes llevarse a cabo usando dos posibles modos:
- ClientWins: Los cambios hechos, se conservan hasta que se llame Save.
- StoreWins: Los cambios son sustituidos por la información del almacén de datos.
Nuestra solución fue, agregar un nuevo método a nuestro repositorio. Este método realiza una actualización de la información, solo que establece el modo a StoreWins.
El código del método es: Como se debe usar
En este ejemplo, se obtiene una entidad solicitud existente en la base de datos. El valor del cupón almacenado es 456, se modifica a 325, al llamar el nuevo método Refresh, se restaura el valor del cupón al original, que era 456.
Este post se realizo con la colaboración de un integrante del equipo de trabajo, Julio Ávila. Gracias.
No hay comentarios:
Publicar un comentario