Ahora yo tengo una pregunta sobre SQL Server: es el manejo de
transacciones, que es diferente de la forma en que VFP las maneja.
Veamos el ejemplo clásico de una factura. Dos tablas, una cabecera y
otra de detalle.
Yo genero dos cursor adapters vacíos con este código
local cCmd
cCmd = [select * from cabecera where 1=0]
y genero el CA 'curCabecera' && tengo una clase que genera CA , pero es
un código largo que no viene al caso
cCmd = [select * from detalles where 1=0]
y genero el CA 'curDetalles'
Para hacerla corta, al grabar hago algo así
cCmd = [begin transaction]
sqlexec(nHandle,cCmd) && con lo que le mando al SQL la orden de iniciar
la transacción
Luego
insert into curCabecera ........
lOK = tableupdate(.t.,.t.,'curCabecera')
if lOK
select curFactura && este es un cursor local que opera con una grilla
scan all
scatter name oFac
insert into curDetalles from name oFac
endscan
lOK = tableupdate(.t.,.t.,'curDetalles')
if lOK
cCmd = 'IF @@TRANCOUNT > 0 COMMIT'
else
cCmd = 'IF @@TRANCOUNT > 0 ROLLBACK'
endif
sqlexec(nHandle,cCmd)
Pero sé que a esto le falta una pata, porque si provoco un error a
propósito en la grabación, para que la segunda tabla no se grabe, por
ejemplo), la segunda tabla no se graba pero la primera se graba igual.
Intenté usar transacciones manuales antes del begin transaction
#DEFINE DB_TRANSMANUAL 2
SQLSetProp(nHandle, "TRANSACTIONS", DB_TRANSMANUAL)
y luego volverlas automáticas después del end transaction
#DEFINE DB_TRANSAUTO 1
SQLSetProp(nHandle, "TRANSACTIONS", DB_TRANSAUTO)
Pero esto hace que los cursor adapters no graben nada
Me gustaría ver qué mecanismo usan Uds para manejar esto. A lo mejor el
hecho de que estoy usando cursor adapters cambia las cosas respecto de
hacer comandos que graben directamente en las tablas del SQL Server.
Después de todo, un CA es como una vista de VFP, con propiedades y
métodos propios, pero vista al fin.
Pero como Pancho parece que la tiene clara, la pregunta es para vos (o
cualquier otro que también la tenga clara)
Rafael Copquin