FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour Consulta sobre ADO a René Flores o quien sepa
Posts: 113
Joined: Wed Jan 10, 2007 08:43 PM
Consulta sobre ADO a René Flores o quien sepa
Posted: Tue Aug 14, 2007 05:37 PM

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

David Lagos S.
Coquimbo-Chile
www.wificafe.cl
webmaster@wificafe.cl
Posts: 840
Joined: Thu Oct 13, 2005 07:05 PM
Consulta sobre ADO a René Flores o quien sepa
Posted: Tue Aug 14, 2007 11:03 PM
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:
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.
Posts: 113
Joined: Wed Jan 10, 2007 08:43 PM
Consulta sobre ADO a René Flores o quien sepa
Posted: Wed Aug 15, 2007 01:30 AM

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 algunos cambios a algunos métodos y a una función. Podrías explicarme con un pequeño ejemplo?
Mil Gracias
David Lagos S.
Coquimbo-Chile

David Lagos S.
Coquimbo-Chile
www.wificafe.cl
webmaster@wificafe.cl
Posts: 840
Joined: Thu Oct 13, 2005 07:05 PM
Consulta sobre ADO a René Flores o quien sepa
Posted: Wed Aug 15, 2007 02:53 PM
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:

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

            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:

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.
Posts: 113
Joined: Wed Jan 10, 2007 08:43 PM
Consulta sobre ADO a René Flores o quien sepa
Posted: Wed Aug 15, 2007 07:43 PM
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.

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


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.
David Lagos S.
Coquimbo-Chile
www.wificafe.cl
webmaster@wificafe.cl

Continue the discussion