[GUFA] OFF TOPIC TRANSACT SQL - manejo de transacciones

2011-05-24 Por tema Rafael Copquin
Ya lo lei, pero sigue la confusión. Voy a experimentar y seguro que por 
prueba y error lo saco. (mis famosas HCS :-) )



El 24/05/2011 12:44, francisco prieto escribió:

Rafa,

Me parece que el temita esta por este link...

http://msdn.microsoft.com/en-us/library/ms131281(v=SQL.100).aspx 
<http://msdn.microsoft.com/en-us/library/ms131281%28v=SQL.100%29.aspx>


Saludos,

Pancho
Cordoba

El 24 de mayo de 2011 12:26, Rafael Copquin <mailto:rcopq...@ciudad.com.ar>> escribió:


La conexión es la misma. No se cambia durante la transacción. Y
por ahora estoy usando ODBC, no ADO.

Lei por ahi que al mandar el comando begin transaction via sqlexec

sqlexec(nHandle,'BEGIN TRANSACTION')

el ODBC pone automáticamente en MANUAL  la transacción ( le manda
el valor 1 ) ¿es asi?

Rafael Copquin


El 24/05/2011 9:28, Omar Bellio escribió:


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

[GUFA] OFF TOPIC TRANSACT SQL - manejo de transacciones

2011-05-24 Por tema francisco prieto
Rafa,

Me parece que el temita esta por este link...

http://msdn.microsoft.com/en-us/library/ms131281(v=SQL.100).aspx

<http://msdn.microsoft.com/en-us/library/ms131281(v=SQL.100).aspx>Saludos,

Pancho
Cordoba

El 24 de mayo de 2011 12:26, Rafael Copquin escribió:

>  La conexión es la misma. No se cambia durante la transacción. Y por ahora
> estoy usando ODBC, no ADO.
>
> Lei por ahi que al mandar el comando begin transaction via sqlexec
>
> sqlexec(nHandle,'BEGIN TRANSACTION')
>
> el ODBC pone automáticamente en MANUAL  la transacción ( le manda el valor
> 1 ) ¿es asi?
>
> Rafael Copquin
>
>
> El 24/05/2011 9:28, Omar Bellio escribió:
>
>  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 ] *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 ma

[GUFA] OFF TOPIC TRANSACT SQL - manejo de transacciones

2011-05-24 Por tema Rafael Copquin
La conexión es la misma. No se cambia durante la transacción. Y por 
ahora estoy usando ODBC, no ADO.


Lei por ahi que al mandar el comando begin transaction via sqlexec

sqlexec(nHandle,'BEGIN TRANSACTION')

el ODBC pone automáticamente en MANUAL  la transacción ( le manda el 
valor 1 ) ¿es asi?


Rafael Copquin


El 24/05/2011 9:28, Omar Bellio escribió:


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] *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 <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_TRANSAUTO1
SQLS

[GUFA] OFF TOPIC TRANSACT SQL - manejo de transacciones

2011-05-24 Por tema Omar Bellio
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] 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 
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.

Int

[GUFA] OFF TOPIC TRANSACT SQL - manejo de transacciones

2011-05-24 Por tema francisco prieto
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 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_TRANSAUTO1
> 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
>
>
>
>


[GUFA] OFF TOPIC TRANSACT SQL - manejo de transacciones

2011-05-24 Por tema Rafael Copquin
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_TRANSAUTO1
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