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 <rcopq...@ciudad.com.ar <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
    <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



Responder a