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

Responder a