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>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 > > > >