Consulta sobre ADO a René Flores o quien sepa

Post Reply
User avatar
metaldrummer
Posts: 113
Joined: Wed Jan 10, 2007 8:43 pm
Location: Coquimbo-Chile
Contact:

Consulta sobre ADO a René Flores o quien sepa

Post by metaldrummer »

según un ejemplo entregado en el foro cuando ejecutamos un comando sql con ado podemos obtener el recorset entregado por el resultado de esta manera:
oSql:CommandText:=cComando
oDatos:=oSql:Execute()

Mi pregunta:
cuales son los métodos y datos que se pueden manejar desde oDatos?
oDatos:MoveFirst(), oDatos:EOF(), oDatos:MoveNext(), oDatos:Fields:Count()
y oDatos:RecordCount() siempre me devuelve -1 y eso me representará problemas a la hora de hacer una consulta del tipo: "SELECT * FROM prueba WHERE usuario='david'", ya que si siempre regresa -1, cómo sabré si encontró o no lo que busco?

Donde puedo obtener información de los métodos y variables que se pueden manejar, ya que he buscado por toleauto dentro de los fuentes de xharbour y dentro de los fuentes de fwh y nada. (Utilizo xharbour desde cvs)

ADORRD tiene problemas a la hora de conectarse con oracle, incluso si modifico el string de conexión que utilizo directamente con ADO solo y puro.

Muchas gracias
David Lagos S.
Coquimbo-Chile
R.F.
Posts: 840
Joined: Thu Oct 13, 2005 7:05 pm

Post by R.F. »

Antes de ejecutar un objeto RecordSet (que no un command, hay diferencia), primero tienes que configurar tu "cursor".

En general los objetos command solo deben ser utilizados cuando vas a realizar una operacion masiva sobre una base de datos, por ejemplo un UPDATE o un Delete.

Cuando vas a visualizar datos o requieres traerte un grupo de datos de tablas para visualizar en un browse por ejemplo lo mejor es utilizar un objeto recordset, previamente configurado:

De mi manual de ADO:

Code: Select all

oRecordSet := TOleAuto():New(“adodb.recordset”)
oRecordSet:LockType := adLockOptimistic
oRecordSet:CursorType := adOpenKeySet
oRecordSet:ActiveConnection(oMiConexion)
oRecordSet:Source := “Select * from Clientes”
**** esto tambien es valido : oRecordSet:Source := “Clientes”
oRecordSet:Open():
Aqui lo que estas haciendo es configurando tu cursor antes de abrirlo, estableces el tipo de bloqueo (adLockOptimistic) y el tipo de cursor (adOpenKeySet), si el cursor no es de este tipo, el record count SIEMPRE devuelve -1.

Dependiendo del tipo de cursor son las cosas que pudes hacer con el recordset

Estos son los tipos de cursores existentes:

adOpenForwardOnly 0 Es el cursor por defecto y nos permite recorrer el Recordset en forma secuencial.

adOpenKeySet 1 Permite movernos hacia delante y atrás. Permite observar las modificaciones en los datos del Recordset , no así si existen ingresos de nuevos registros

adOpenDynamic 2 Permite movernos en cualquier sentido, viendo cualquier modificación, ingreso o eliminación de datos del Recordset.

adOpenStatic 3 Permite movernos en cualquier sentido, pero no se verá ningún cambio ocurrido en la tabla.
Saludos
R.F.
User avatar
metaldrummer
Posts: 113
Joined: Wed Jan 10, 2007 8:43 pm
Location: Coquimbo-Chile
Contact:

Post by metaldrummer »

Definitivamente tu nivel de conocimientos es increíble un millón de gracias.
Por último una pregunta más:
Como utilizando este modelo puedo implementar un browse. Vi que hay que hacer _ a algunos métodos y a una función. Podrías explicarme con un pequeño ejemplo?
Mil Gracias
David Lagos S.
Coquimbo-Chile
R.F.
Posts: 840
Joined: Thu Oct 13, 2005 7:05 pm

Post by R.F. »

El browse "ta chupao".... solo hay que saber como definirlo y reescribir algunas propiedades.

El wbrowse sirve prácticamente para desplegar en pantalla cualquier cosa, textos, tablas dbfs, arrays, y hasta recordsets de ado, asi que lo que vamos a definir son las columnas del browse llamando a la coleccion FIELDS() del recordset:

Code: Select all

      @ 0, 0 LISTBOX oBrw FIELDS oRecordSet:Fields(0):value,;
                           oRecordSet:Fields(1):value,;
                           oRecordSet:Fields(2):value,;
                           oRecordSet:Fields(3):value,;
                           oRecordSet:Fields(4):value,;
                           oRecordSet:Fields(6):value;
     HEADERS "Codigo","Tipo","Canal","Nombre","Ciudad","Pais" OF oWndBrw
Después le tenemos que "enseñar" al browse como debe moverse en base al recordset, para esto reescribiremos algunas propiedades del browse para que utilice las propiedades de movimiento del recordset:

Code: Select all

            oBrw:bLogicLen = { || oRecordSet:RecordCount }
            oBrw:bGoTop    = { || oRecordSet:MoveFirst() }
            oBrw:bGoBottom = { || oRecordSet:MoveLast() }
            oBrw:bSkip     = { | nSkip | Skipper( oRecordSet, nSkip ) }
            oBrw:cAlias    = "ARRAY"
La propiedad mas importante es la ::bSkip que indica el numero de registros que se debe de mover el browse ya sea para adelante o para atras para poder desplegar los datos, en el ejemplo anterior, haces una llamada a la función SKIPPER, aquí la tienes:

Code: Select all

STATIC FUNCTION SKIPPER( oRs, nSkip )

    LOCAL nRec := oRs:AbsolutePosition

    oRs:Move( nSkip )

    IF oRs:EOF; oRs:MoveLast(); ENDIF
    IF oRs:BOF; oRs:MoveFirst(); ENDIF

RETURN oRs:AbsolutePosition - nRec
Y eso es todo, mas simple ni hacer limonada en verano.

Eso si muy imporntate, para poder "browsear" un recordset, este tiene que ser del tipo adOpenKeySet, si no, no te puedes mover sobre el.
Saludos
R.F.
User avatar
metaldrummer
Posts: 113
Joined: Wed Jan 10, 2007 8:43 pm
Location: Coquimbo-Chile
Contact:

Post by metaldrummer »

Mil Gracias por el ejemplo René.
Todo estaba ok, pero por algún motivo, la rutina dejó de funcionar. Se cae al realizar el "oDatos:Open()" del recordset.
Aquí va el código y al final como estoy llamando a la función.

Code: Select all

FUNCTION SQL( cComando)
   LOCAL lOK:=.T.

   TRY
      MsgInfo( "Línea 75", "rutinasdeconexion.prg")
      oCon:=toleauto():new("adodb.connection")
      //oCon:=CreateObject("adodb.connection")
   CATCH oError
      MsgStop( "Línea 79", "rutinasdeconexion.prg")
      lOK:=.F.
   END
   IF lOk
      oCon:ConnectionString:=cStringConexionLocal
      TRY
         MsgInfo( "Línea 85", "rutinasdeconexion.prg")
         oCon:Open()
      CATCH oError
         MsgStop( "Línea 88", "rutinasdeconexion.prg")
         lOK:=.F.
         oCon:=NIL
      END
      IF lOk
         //creamos un objeto recordset para ejecutar los queries
         TRY
            MsgInfo( "Línea 95", "rutinasdeconexion.prg")
            oDatos:=TOleAuto():New("adodb.recordset")
            //oDatos:=CreateObject("adodb.recordSet")
         CATCH oError
            MsgStop( "Línea 99", "rutinasdeconexion.prg")
            lOK:=.F.
            oCon:Close()
            oDatos:=NIL
            oCon:=NIL
         END
         IF lOk
            oDatos:CursorLocation  := adUseServer //adUseClient
            oDatos:LockType := adLockOptimistic
            oDatos:CursorType := adOpenKeyset
            oDatos:Source:=cComando
            oDatos:ActiveConnection(oCon)
            TRY
               MsgInfo( "Línea 112", "rutinasdeconexion.prg")
               oDatos:Open()
            CATCH oError
               MsgStop( "Línea 115", "rutinasdeconexion.prg")
               MsgStop(oError:Operation,"adodb.recordset")
               lOK:=.F.
               oCon:Close()
               oDatos:=NIL
               oCon:=NIL
            END
         ELSE
            oCon:Close()
            oDatos:=NIL
            oCon:=NIL
         ENDIF
      ELSE
         oCon:Close()
         oCon:=NIL
      ENDIF
   ELSE
      oCon:=NIL
   ENDIF
RETURN lOk

Code: Select all

IF Sql("SELECT pass_u,pagina FROM EXT1_CENTROCLIP.USUARIO WHERE trim(nombre_u)='"+Alltrim(cUsuario)+"'")
...
...
ENDIF
cStringConexionLocal es una variable definida como pública que contiene el string de conexión a Oracle 10gR2.
¿Qué podrá ser?
Saludos y gracias nuevamente
David Lagos S.
Post Reply