PDA

Ver la Versión Completa : problema con mastersource


Yoli
31-03-2005, 05:34:58
Hola a todos, estoy desarrollando un formulario maestro/detalle, con delphi 6, firebird 1.5 e IBX. Para esto tengo 2 TIBtable.

en el TIBtable1 esta la tabla maestro (la clave principal es ID_COTIZACION) y en el TIBtable2 esta la tabla detalle (la clave foranea es ID_COTIZACION1), y en esta tengo como mastersource a dsMaestro (datasource), y en el field link desingner le dije: ID_COTIZACION1 - ID_COTIZACION. Ahora bien, el problema que tengo es que al momento de guardar, se guardan todos los campos en la tabla maestro y todos los campos de detalle excepto el campo ID_COTIZACION1, es decir, no guarda automaticamente en la tabla detalle el campo que relaciona al maestro con el detalle, es como si no funcionara el mastersource. el codigo que tengo en el boton guardar es:

dsCotizacion.DataSet.Post;
dsCotizacion.DataSet.Refresh;

bueno espero puedan ayudarme con este problema. Saludos y gracias de antemano.

jachguate
31-03-2005, 15:35:14
Estrictamente no es que el master/detail no funcione, simpelemente que delphi no asigna el valor de los campos que la relacionan con el padre a la tabla hija.

Vos lo podes solucionar fácilmente en el evento OnNewRecord de la tabla hija:


Procedure Forma1.TablaHijaNewRecord(DataSet : TDataSet);
Begin
TablaHijaNumeroFactura.AsInteger := TablaPadreNumeroFactura.AsInteger;
end;


Suponiendo en este caso, que el campo NumeroFactura es el que relaciona ambas tablas.

Hasta luego.

;)

Yoli
01-04-2005, 16:20:57
Gracias por responder jachguate, hice lo que me dijistes:

Vos lo podes solucionar fácilmente en el evento OnNewRecord de la tabla hija:


Procedure Forma1.TablaHijaNewRecord(DataSet : TDataSet);
Begin
TablaHijaNumeroFactura.AsInteger := TablaPadreNumeroFactura.AsInteger;
end;


Suponiendo en este caso, que el campo NumeroFactura es el que relaciona ambas tablas.

Y me quedo asi.

procedure TdmTablas.IBTCotizacionDNewRecord(DataSet: TDataSet);
begin IBTCotizacionDID_COTIZACION1.AsInteger:=IBTCotizacionID_COTIZACION.AsInteger;
end;

pero ahora me lanza otro error que dice:

'violation of FOREING KEY constratint "FK_ID_COTIZACION1" on table "COTIZACIOND"

Esto me pasa a la hora de insertar el 2do. registro en el grid, es decir, cuando ingreso el primer registro en el grid todo bien, pero en el momento que presiono la flecha hacia abajo para que aparezca la otra linea en el grid , me lanza este error. no se que estoy haciedo mal, espero puedas ayudarme con estoy. Saludos y gracias de nuevo.

jachguate
01-04-2005, 16:33:20
Ahora ocurre que estas intentando insertar el detalle en la base de datos sin haber insertado primero el padre. Hay varias formas de enfrentarlo... lo que me parece mas adecuado dado tu planteamiento es hacer algo como esto en el evento BeforePost de la tabla hija:


Procedure TablaHijaBeforePost(parametros... );

Begin
if TablaPadre.State = dsInsert Then
TablaPadre.Post;
end;

Lo que forzará a que el registro padre se inserte primero a la base de datos.

Hasta luego.

;)

Yoli
01-04-2005, 18:23:37
[QUOTE=jachguate]Ahora ocurre que estas intentando insertar el detalle en la base de datos sin haber insertado primero el padre. Hay varias formas de enfrentarlo... lo que me parece mas adecuado dado tu planteamiento es hacer algo como esto en el evento BeforePost de la tabla hija:


Procedure TablaHijaBeforePost(parametros... );

Begin
if TablaPadre.State = dsInsert Then
TablaPadre.Post;
end;

Lo que forzará a que el registro padre se inserte primero a la base de datos.

Gracias por tu respuesta, lo voy hacer, pero antes de hacer te pregunto. Si inserto del maestro(padre) en la base de datos antes de insertar los registro de detalle (hijo) y deseo cancelar en algun momento, significa que tengo que eliminar el registro padre que inserte. Esta es la mejor forma de hacerlo?. lo que intento hacer es insetar todo de una vez, de manera que si deseo cancelar en algun momento, no tengo que eiliminar nada de la base de datos. segun tú, ¿ cual es la mejor forma de insertar registros en un formulario maestro/detalle? . Saludos

jachguate
01-04-2005, 18:38:52
Pues eso nuevamente hay varias formas de enfrentarlo.

La primera y mas simple, es encerrar todo en una transacción (no poner las transacciones automáticas), y si después se quiere cancelar bastará con hacer Transaccion.RollBack. Es una solución mas simple pero puede ocasionarte conflictos con locks en la base de datos, principalmente si el usuario A decide ir a almorzar habiendo dejado abierta la transacción, cosa poco recomendable.

Otra, un poco mas compleja pero mas funcional, es mantener todas las actualizaciones en cache y voltearlas luego todas juntas a la base de datos, sobre lo cual te recomiendo buscar y leer alguna información. Comenzá por la ayuda de la propiedad CachedUpdates.

Espero haberte ayudado con esta pequeña explicación.

Hasta luego

;)

Yoli
01-04-2005, 18:48:29
Espero no molestarte con tantas preguntas y de nuevo gracias por contestarlas. Ya gice el codigo del beforepost, y ahora me sale un error que dice: stackoverflow y aparce aparece al momento de presionar la flecha abajo el en grid despues de haber insertado el primer registro en el grid. Sabes a que se debe esto? . gracias. saludos

Yoli
01-04-2005, 18:49:49
Espero no molestarte con tantas preguntas y de nuevo gracias por contestarlas. Ya hice el codigo del beforepost, y ahora me sale un error que dice: stackoverflow y aparce aparece al momento de presionar la flecha abajo el en grid despues de haber insertado el primer registro en el grid. Sabes a que se debe esto? . gracias. saludos

jachguate
01-04-2005, 19:29:49
El stack overflow ocurre regularmente con una mala llamada recursiva que llena la pila, puesto que no termina nunca la recursión.

Aqui seguramente hay una llamada recursiva indirecta. No puedo probarlo ahora con las ibx, pero estoy casi seguro que se trata de un problema originado en el código que tu tengas asociado a los eventos de la tabla padre (quizas también en el beforepost de la tabla padre).

Lo que te recomiendo es poner un breakpoint en el evento BeforePost de la tabla hija, y una vez llegada la ejecución a ese punto, continuar con la ejecución paso a paso, de manera que vos mismo(a) encontres donde se origina la recursión.

¿una solución?.. quizas una variable booleana sea suficiente (normalmente llamada bandera)... pero eso dependerá de lo que encontres en tu búsqueda.

Hasta luego.

;)

Yoli
01-04-2005, 19:30:07
Ya estoy buscando informacion sobre el cachedupdates. Gracias por orientarme con respcto a este tema. Ahhh y ya soluciones lo del satck overflow. Volvi a colocar un codigo que habia borrado en el evento OnEnter del grid:

if (DSCotizacion.DataSet.State = dsEdit) or (DSCotizacion.DataSet.State = dsInsert) then
begin
DSCotizacion.DataSet.Post;
DSCotizacion.DataSet.Refresh;
end;

De nuevo gracias por tu respuestas y recomendaciones, me fuiste de gran ayuda. Saludos.