Rafa, lo que te debe estar pasando es que la conexión que usás
para los CursorAdapters es distinta a la que usa el SqlExec, por
lo tanto, las transacciones y las otras instrucciones “no están
viendo el mismo canal”, por así decirlo.
La solución de Pancho, como podrás ver, usa la misma conexión ADO
para toda la operatoria entonces no tiene dramas.
Otra observación, me parece que si cambiás tu bloque de
instrucciones Scan Alll… EndScan por una sola instrucción Insert
into… Select… from… vas a tener mejor rendimiento (aunque los
registros sean poquitos, me parece más elegante, pero esto es
sólo una cuestión de gustos)
Salute!
*De:*GUFA@mug.org.ar <mailto:GUFA@mug.org.ar>
[mailto:GUFA@mug.org.ar] *En nombre de *francisco prieto
*Enviado el:* martes, 24 de mayo de 2011 08:38 a.m.
*Para:* GUFA List Member
*Asunto:* [GUFA] OFF TOPIC TRANSACT SQL - manejo de transacciones
Rafa,
No es que la tenga tan clara sino que me crucé con tantos
quilombos en implementaciones que decidí no utilizar
cursoradapters, sino una clase propia a la que la llame
rstocursor... pero eso es harina de otro costal y si queres en
otro momento la vemos.
Utilizo, gracias a esta clase ADODB y para trabajar con
transacciones simplemente hago esto:
oConexionActual.Execute("SET IMPLICIT_TRANSACTIONS OFF")
oConexionActual.Execute("BEGIN TRANSACTION")
Luego por ejemplo hago un insert en el motor de la siguiente forma
lcSql="Insert Into ColaEspera
(Orden_cEsp,F_Llegada,Nro_Turno,Estado,Flg_Espera,IdActuante,IdDerivad)
VALUES ("+;
"'"+cOrden.Nro_Turno+"',"+;
"'"+lcLlegada+"',"+;
"'"+cOrden.Nro_Turno+"',"+;
"'ES',"+;
"'P',"+;
"NULL"+","+;
"'"+cOrden.IdDerivador+"')"
Try
oConexionActual.Execute(lcSql)
Catch To loError
llHuboError=.T.
lcTexto="La instruccion "+Chr(13)+Chr(10)+;
lcSql+Chr(13)+Chr(10)+;
"emitio el error "+Alltrim(Str(loError.ErrorNo))+" -
"+loError.Message
Strtofile(Transform(Date(),"@E")+" "+Ttoc(Datetime(),2)+"
"+_Screen.UsrName+" ("+;
ALLTRIM(_Screen.AppName)+")
"+lcTexto,_Screen.DirApp+_Screen.MisErrores.ArchLog,1)
Endtry
y finalmente, cuando termino con todo...
If llHuboError
oConexionActual.Execute("ROLLBACK TRANSACTION")
Messagebox("Se produjo un error interno durante la
grabación.",16,"Avise a Sistemas")
Else
oConexionActual.Execute("COMMIT TRANSACTION")
Endif
Esta operatoria nunca me causo los errores que vos mencionas....
Tengo otros quilombos (quien no? :)), pero hasta el momento con
SqlServer fueron todas sonrisas...
Saludos,
Pancho
Cordoba
El 24 de mayo de 2011 08:24, Rafael Copquin
<rcopq...@ciudad.com.ar <mailto:rcopq...@ciudad.com.ar>> escribió:
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