Hola a todos!
Estoy diseñando un formulario muy simple que sirve para inscribir personas y determinar la función de cada uno. Básicamente mi modelo de datos es una relación de N:M (como la llamada modelo de datos). En toba (v. 1.4.8) defino el datos relación con se ve en la figura datos_tabla y las relaciones quedan como en la figura “relaciones”. El problema que tengo es que al armar la operación e intentar ejecutar el sincronizado de los datos, obtengo el error La tabla persona_funcion requiere ingresar al menos 1 registro/s (se encontraron sólo 0). , esto es porque le digo en el editor que el mínimo para la relación función_persona es 1. Si no pongo esta condición, la operación me da de alta los registros en la tabla persona y la funciones, pero no escribe nada en la tabla de persona_función. Realmente no se que es lo que estoy haciendo mal, me podrían ayudar?
Hola Victor,
los componentes de persistencia de toba fueron pensados para manejar cardinalidades 1:N, generalmente las N:M las manejamos como caso particular ya que no entran en el esquema.
Con respecto al error, al sincronizar en las relaciones se traslada el cursor de la tabla padre a la tabla hija en el campo especificado para la relacion, el problema en tu caso es que el registro en la tabla esta conformado unicamente por las claves las cuales deben ser transmitidas desde los padres al hijo, el detalle es que no existen campos para hacer una llamada al metodo nueva_fila() y que asi quede grabado en el estado interno del datos_tabla que debe agregar un registro.
Por otro lado te vas a encontrar con el inconveniente en la carga, ya que tenes 2 tablas padres… pero el toba_datos_relacion esta pensado para que la raiz del arbol sea una unica tabla padre a partir de la cual se van cargando las tablas hijas. Osea que en definitiva no solo vas a tener un inconveniente al momento de crear un registro sino tambien al momento de cargarlo para edicion.
Generalmente el metodo que utilizamos nosotros es el siguiente, en tu caso lo que hariamos es transformar la relacion N:M en una relacion 1:M con un N fijo… por ejemplo yo lo que haria es en ese caso seria quitar la tabla funcion de la relacion, dejando unicamente a personas y persona_funcion con la cardinalidad que te decia. Lo que haria seria ir agregando funciones (mediante un ML o cualquier otra forma) al datos_tabla ‘persona_funcion’ para una persona fija y particular, cuando realizo la carga para edicion ingreso por la persona, asi que cargo todas las funciones que tiene asociadas y en caso de editar para cambiar alguna funcion por otra, simplemente elimino todas las filas asociadas en ‘persona_funcion’ y luego doy de alta nuevamente las que me quedaron ingresadas. De esta forma la persona siempre tiene asociadas las funciones que le corresponde, quizas no queda tan representativo con respecto a la relacion en el modelo de datos, pero es una manera que no requiere tanto codigo y nos permite aprovechar las bondades de los componentes de persistencia.
Espero que mi explicacion no sea demasiado enredada XD.
Saludos
Richard:
Gracias por la respuesta, es un poco enredada pero se entiende los que me decis. La otra cosa que estaba pensando hacer es dejar en el editor los atributos min filas y max filas en blanco para la tabla persona_funcion (con esto evito que toba sincronize automáticamente). De este modo lo que hace toba es darme de alta el registro en personas y el registro en funciones, inmediatamente después de ejecutar la orden sincronizar lo que tendría que hacer es un SELECT last_value FROM public.personas_seq; para obtener el último id insertardo y lo mismo con funciones y escribirlo manualmente en la tabla persona_funciones. Lo que estaba pensando… ¿el datos tabla no tiene un método que me devuelva el valor? leí la documentación y no lo encuentro. Esto es para evitar un problema de concurrencia ya que si dos personas sincronizan al mismo tiempo puede explorar todo bueno, no para tanto, pero me puede generar inconsistencias. Igualmente utilizando esta opción debería hacer unn procedimiento similar al que me decis al momento de la modificación.
Hola Victor,
te hago una consulta, los datos para las tablas de personas y funcion se dan de alta en el mismo momento?, yo creia que simplemente dabas de alta la asociacion entre ambas tablas.
Si los das de alta en el mismo momento, entonces te diria que no necesitas una relacion, simplemente podes tener los 3 datos_tabla separados y manejar la sincronizacion de forma manual.
Por ej algo que se me ocurre para eso es… en un evento guardar algo asi:
function evt__guardar()
{
$this->dep('tabla_personas')->get_persistidor()->desactivar_transaccion();
$this->dep('tabla_funcion')->get_persistidor()->desactivar_transaccion();
$this->dep('tabla_persona_funcion')->get_persistidor()->desactivar_transaccion();
toba::db()->abrir_transaccion();
try {
$this->dep('tabla_personas')->sincronizar();
$id_persona = toba::db()->recuperar_secuencia('personas_seq');
$this->dep('tabla_funcion')->sincronizar();
$id_funcion = toba::db()->recuperar_secuencia('funcion_seq');
$this->dep('tabla_persona_funcion')->nueva_fila(array('id_persona' => $id_persona, 'id_funcion' => $id_funcion));
$this->dep('tabla_persona_funcion')->sincronizar();
toba::db()->cerrar_transaccion();
}catch($e toba_error_db) {
toba::db()->abortar_transaccion();
throw $e;
}
}
No se, es una idea que me viene sobre como manejarlo si es que se necesitan dar de alta los valores en ese momento, ademas de la relacion.
Fijate que ahi esta el tema de la recuperacion de la secuencia… lo unico que debes tener en cuenta es que tiene que ser dentro de una transaccion siempre, sino no funca.
Saludos
Si justamente los campos en las dos tablas se dan de alta al mismo tiempo. Igualmente, es buena la idea que me das, así que ya estoy implementandolo. Muchas gracias!