ADO no me funciona en una tabla en especifico

ADO no me funciona en una tabla en especifico

Postby jllinas » Mon Mar 27, 2006 12:06 am

Hola a todos,

... no tienen idea de lo que he buscado informacion sobre esto en la red, y finalmente he caido aqui, pues he llegado a la conclusion de que solamente Ustedes podran darme luz en esto.

Se trata del ampliamente expuesto en la red, problema del mensaje de error que aparece:

"No se puede encontrar la fila para su actualizacion: algunos valores han cambiado desde la ultima vez que se leyo"

A partir de alli, parece que la conexion con el recorset desaparece, pues todas las instrucciones que siguen aparecen con error, y nunca se ejecuta.


TOdo esto aparece al ejecutar una instruccion ::oRs:Update().

No me ocurre con todas las tablas de la base de datos, sino con una sola de ellas (hasta ahora no he comprobado con todas las tablas). A TODAS las tablas de la base de datos se le ha agregado un columna, al inicio, llamada "noreg", entero, auto_increment que lo utilizo como llave primaria.

Estoy usando xHarbour 0.99.3, FWH24, Borland 5.5.1, MySQL 3.23 (en modo local) e instale MyODBC 2.50

Hasta ahora he tratado lo siguiente:

1.- realizo las sustituciones con ::oRs:Fields(n):value := 'valor a cambiar', cambie a ::oRs:Fields('nombre del campo'):value := ´valor a cambiar', y el error persiste.

2.- realizo el ::oRs:Update() al final de las sustituciones. Cambie a realizar las sustituciones por ::oRs:Update('nombre del campo', 'valor a cambiar'), y el error persiste.

3.- Utilizo OPTION=3, y la cambie a OPTION=16387, y el error persiste.

4.- marque las dos primeras opciones en la configuracion de MyODBC en el COntrol Panel, y el error persiste.

5.- Ejecute todo con la opcion de Trazas seleccionada en Control Panel, y el archivo no me dice de nikngun error (o no se interpretarlo), y tambien seleccione la opcion de trazas con OPTION=7, y lo mismo.

6.- He leido todas las news de FW, y veo que nadie reporta esto.

7.- He buscado en la red, y aunque mucha gente lo reporta, nadie llega a una solucion. Algunos suguieren soluciones para VB, tales como utilizar los campos numericos en formato DOUBLE y no FLOAT, agregar un campo timestamp "dummy" a las tablas. Esto no lo he tratado aun.

Mi string de conexion es:

DRIVER={MySQL}; SERVER=localhost; DATABASE=XXXXXXX; UID=jllinas; PWD=XXXXXXXX; OPTION=16387

AL momento de conectar, el CursorLocation es adUseClient.

Para crear el recordset hago:

::oRs := CreateObject("ADODB.Recordset")
::oRs:Open( cQuery, uConn, nCursorType, nLockType, nOptions )

donde nCursorType es adOpenKeySet, nLockType es adLockOptimistic y nOptions es adCmdUnknown

He comprobado, y realmente el registro no se ha movido, comprobado entre la lectura y la escritura.

... no se que mas comprobar, a ver que estoy haciendo mal...

Me estoy tirando de los pelos que ya no me quedan!

AYUDA.... POR FAVOR !!!!!
Julio Llinás
Visita mi Blog en http://mangucybernetico.blogspot.com/
xHarbour 1.1.0 + FWH810 + Borland 5.5.1
User avatar
jllinas
 
Posts: 189
Joined: Fri Oct 14, 2005 12:33 am
Location: Santo Domingo, Dominican Republic

Prueba poner esto

Postby fsandoval » Mon Mar 27, 2006 1:57 pm

Julio yo lo creo de la sig. manera y me ha funcionado.

oEMPRESAS := CREATEOBJECT( "ADODB.Recordset" )
oEmpresas:CursorLocation := 3
oEmpresas:CursorType := 3
oEmpresas:LockType := 3
oEmpresas:MaxRecords := 0

espero te funcione.
fernando sandoval ruiz
fsandoval@hotmail.com
fsandoval
 
Posts: 71
Joined: Mon Oct 10, 2005 9:24 pm
Location: aguascalientes

Postby jllinas » Mon Mar 27, 2006 5:23 pm

Fernando,

Gracias adelantadas por contestar...

En efecto, comparando la forma que lo hago con lo que me expresas aqui, tenía solo diferencia en el ::oRs:CursorType, que al tu colocarle un valor de 3, significa que has seleccionado adOpenStatic. Ya habia observado que algunos otros compañeros asi lo hacian.

Lo cambié y el problema persiste. Lo probe de nuevo con la tabla en interes, y no funciona (reporta el mismo error), mientras que en otras tablas el problema no ocurre, y el ABM ocurre normalmente.

Una cosa que no entendi: incluyes aqui el parámetro ::oRs:MaxRecords := 0. ¿Que significa esto? no lo habia visto por ninguna otra parte...

Por otro lado, y ahora para todos:

¿En ADO existen nombres reservados, que no puedan utilizarse para nombres de columnas? Se que en MySQL existen, y ya pase por esta, pero no he verificado en ADO.... ¿Alguien sabe de esto?

Gracias a todos,
Julio Llinás
Visita mi Blog en http://mangucybernetico.blogspot.com/
xHarbour 1.1.0 + FWH810 + Borland 5.5.1
User avatar
jllinas
 
Posts: 189
Joined: Fri Oct 14, 2005 12:33 am
Location: Santo Domingo, Dominican Republic

::ORs:Maxrecords

Postby fsandoval » Mon Mar 27, 2006 6:56 pm

Julio , segun lo que indica la documentacion es esto.

Nos permite fijar el número máximo de registros que aceptará el objeto Recordset. El valor por defecto es 0 e indica que no existirá límite.

si quieres puedes anviarme la tabla o la bd, para ver si tambien a mi presenta los mismo problemas.

saludos
fernando sandoval ruiz
fernando sandoval ruiz
fsandoval@hotmail.com
fsandoval
 
Posts: 71
Joined: Mon Oct 10, 2005 9:24 pm
Location: aguascalientes

Postby jllinas » Wed Mar 29, 2006 7:04 pm

Gracias Fernando,

Dos cosas nuevas en esto:

- Primero, no se como pasarte la tabla en la cual tengo problemas. Yo utilizo MySQL, y todo depende de con cual motor de BD vas a buscar reproducir el mismo error que me pasa. Puedo enviarte la tabla en DBF a partir de la cual he creado la de MySQL (solo tiene 10 registros para probar), pero tú me diras.

- "Conversando" con José Luis Capel por MSN, me ha sugerido que integre las pruebas con el metodo Supports(), a ver si es que los metodos ::oRs:Update() y la propiedad ::oRs:BookMark estan soportadas por el proveedor (MySQL). El caso es que SI estan soportadas ambas. Anexo mas abajo el metodo Save(), que es con el cual me ocurre el problema. Se trata del mismo método Save() propuesto por JLC y que fuera publicado en su Blog..... pero muy, muy modificado, pues trato los valores en un buffer, y luego simplemente los grabo con el Update().

-----------------------------------------
METHOD Save() CLASS tAdoRs

LOCAL oError
LOCAL lResult
LOCAL n, nFields
LOCAL lChange := .F.
LOCAL uBkMrk
LOCAL cType

lResult := .T.

TRY
if ::lNeedUpd
if ::lBuffer
for n := 1 to len( ::aBuffer )
if ::oRs:Fields(n-1):value <> ::aBuffer[n]

cType := ::FieldType( n )
cName := ::FieldName( n )

do case
case cType = "D"
::oRs:Fields( cName ):value := if(::aBuffer[n]=CTOD(""), NIL, DTOC( ::aBuffer[n] ) )

otherwise
::oRs:Fields( cName ):value := ::aBuffer[n]

endcase
lChange := .T.
endif
next
endif

if lChange
MsgInfo( "Soporta el metodo UPDATE(): "+IIF(::oRs:Supports( adUpdate ),"Si","No" ) )
MsgInfo( "Soporta la propiedad BOOKMARK: "+IIF(::oRs:Supports( adBookMark ),"Si","No" ) )
IF ::oRs:Status() == adRecModified
::oRs:Update()
uBkMrk := ::Recno()
::oRs:Requery()
::Goto( uBkMrk )
ENDIF
endif
::lNeedUpd := .F.
endif

CATCH oError
lResult := .F.
MsgStop(oError:Operation+CRLF+;
oError:Description+CRLF+;
"Tabla: "+::cAlias+CRLF+;
"Columna: "+STR(n),"Ado Recordset - Método Save()")
END

RETURN lResult

Gracias anticipadas por cualquier sugerencia...
Julio Llinás
Visita mi Blog en http://mangucybernetico.blogspot.com/
xHarbour 1.1.0 + FWH810 + Borland 5.5.1
User avatar
jllinas
 
Posts: 189
Joined: Fri Oct 14, 2005 12:33 am
Location: Santo Domingo, Dominican Republic

Postby jlcapel » Thu Mar 30, 2006 7:52 am

Julio,

Prepara, por favor, un ejemplo autocontenido que muestre el problema que indicas. A ver si vemos lo que te está pasando.

Saludos,
José Luis Capel
User avatar
jlcapel
 
Posts: 229
Joined: Wed Oct 12, 2005 5:32 pm
Location: Valencia - España

Postby jlcapel » Thu Mar 30, 2006 8:08 am

Julio:

a. ¿Como creas el recordset? Muéstrame el código

b. ¿Como haces para modificar un registro? Muéstrame el código

c. ¿Como haces para grabar el registro? Muéstrame el código.

El mensaje que te aparece:

"No se puede encontrar la fila para su actualizacion: algunos valores han cambiado desde la ultima vez que se leyo"


A mi me ha aparecido cuando:

a. El registro que voy a grabar ya no existe en el recordset.
b. El recordset que me he traido no tiene clave primaria.

Saludos,
José Luis Capel
User avatar
jlcapel
 
Posts: 229
Joined: Wed Oct 12, 2005 5:32 pm
Location: Valencia - España

Cual es el link del articulo

Postby fsandoval » Thu Mar 30, 2006 6:31 pm

Cual es el link del articulo donde publico jcapel.

si no es muy grabde la bd puedes enviarmela.

gracias.
fernando sandoval ruiz
fernando sandoval ruiz
fsandoval@hotmail.com
fsandoval
 
Posts: 71
Joined: Mon Oct 10, 2005 9:24 pm
Location: aguascalientes

Postby jllinas » Thu Mar 30, 2006 11:20 pm

Bueno, a ver si "mato" dos de un tiro:

Primero, dejame comenzar con el último, Fernando:

- Para ver las clases originales sugeridas por jcapel, puedes visitar su blog que esta en http://www.capelblog.com

- La tabla que me pides puedes descargarla en este enlace http://www.ssp.com.do/clientes.dbf

Ahora para lo que me pide José Luis:

Debo comenzar por colocar a la disposición de todos las clases originales, propuestas por ti, modificadas por mi. Buscaré crear en mi blog un articulo donde comentaré los cambios que le he realizado. Por ahora, la puedes descargar de aqui http://www.ssp.com.do/adoclass.zip, el cual contiene las clases ADOCONN, ADORS y el archivo ADO.CH modificado.

a. ¿Como creas el recordset? muestrame el código


Primero la conexion. Esto lo hago al momento de empezar con nuestro sistema, para conectar con ADO:


Code: Select all  Expand view  RUN
   oConexionAdo := tAdoConn():New()
   lConectado   := oConexionAdo:Open( MIP )

   CursorWait()
   oTables := oConexionAdo:OpenSchema( adSchemaTables )
   aFiles  := {}
   DO WHILE !oTables:EOF()
      AADD( aFiles, oTables:Fields(2):value )
      oTables:MoveNext()
   ENDDO
   oTables:Close()
   CursorArrow()

   if len(aFiles) == 0
      MsgAlert("No existen tablas sobre esta Base de datos, retornando...", "Busqueda de Tablas con ADO")
      oConexionAdo:Close()
      QUIT
   endif


oCOnexionAdo es una variable (objeto) pública, MIP es la cadena de conexion, que para mi caso es:

Code: Select all  Expand view  RUN
MIP := "DRIVER={MySQL}; SERVER=localhost; DATABASE=richardcar; UID=jllinas; PWD=XXXXXXXX; OPTION=16387"     


Luego, para crear el recordset, utilizo este código:

Code: Select all  Expand view  RUN
   oDbf := tAdoRs():New()

   oDbf:oRs:CursorLocation := adUseClient
   oDbf:oRs:CursorType     := adOpenForwardOnly
   oDbf:oRs:LockType       := adLockOptimistic

   lReturn := oDbf:Open( cQuery, oConexionAdo:oConnection, adOpenKeyset, adLockOptimistic, adCmdUnknown, cAlias,, cOrder )


b. ¿Como haces para modificar un registro? Muéstrame el código


Como puedes ver, para modificar un registro, siempre lo cargo a una variable tipo DATA de la clase ADORS que se llama ::buffer, y que es un arreglo simple y sencillo del registro donde está el puntero en el recordset. Este arreglo se accesa haciendo mencion a

"nombre del recordset":"nombre de la columna"

Por ejemplo, para la tabla que me da problemas, llamo "oClientes" al recorset, y para cambiar el valor en la columna llamada "nombre", simplemente hago

Code: Select all  Expand view  RUN
oClientes:Nombre := "JUAN PEREZ"


Pero todo esto se hace en el buffer. Si vez el método ON ERROR al final de la clase ADORS, podrás ver que allí se realiza este milagro (no es un truco de mi autoría... lo segui simplemente después de ver a muchos hacerlo así).

Luego de esto, solo me queda grabar el registro...

Para "cargar" el registro desde el recordset tengo la siguiente función:

Code: Select all  Expand view  RUN
FUNCTION DBGET( oDbf, lAgrega )
LOCAL nRecno := 1
IF lAgrega
      oDbf:Blank()
ELSE
   oDbf:Load()
ENDIF
RETURN NIL


donde oDbf es la variable objeto del recorset (para mi ejemplo, oClientes).

c. ¿Como haces para grabar el registro? Muéstrame el código.


Luego, para grabarlo, tengo otra función, parecida a la anterior, pero que "coloca" el registro en el recordset:

Code: Select all  Expand view  RUN
FUNCTION DBPUT( oDbf, lAgrega )
IF lAgrega
   oDbf:Append()
   oDbf:Save()
ELSE
   oDbf:Save()
ENDIF

RETURN NIL


Creo que esto es todo. La tabla que me dá problemas la puedes descargar (en formato DBF) desde un enlace que incluí al principio de este mensaje.

Ojala y puedas ver algo que no este yo viendo ahora !!!

Gracias anticipadas,
Julio Llinás
Visita mi Blog en http://mangucybernetico.blogspot.com/
xHarbour 1.1.0 + FWH810 + Borland 5.5.1
User avatar
jllinas
 
Posts: 189
Joined: Fri Oct 14, 2005 12:33 am
Location: Santo Domingo, Dominican Republic

Estos son los cambios

Postby fsandoval » Fri Mar 31, 2006 4:46 pm

Julio no se que problema haya, luego de hacer varias pruebas , el cambio el siguiente, oRs:Fields("Nombre"):= alltrim(cNombre) , no se harbour o xharbour agrege algun caracter al terminar de capturar o lo espacion en blanco no sean aceptados por ado.

de echo tambien tengo el mismo problema con una tabla, que ya estaba funcionando bien.

a el link donde esta la aplicacion no funciona, pero mandamelo a fernandosando@gmail.com

saludos.
fernando sandoval ruiz
fernando sandoval ruiz
fsandoval@hotmail.com
fsandoval
 
Posts: 71
Joined: Mon Oct 10, 2005 9:24 pm
Location: aguascalientes

Postby jlcapel » Mon Apr 03, 2006 7:55 am

Julio,

Mándame, por favor, un ejemplo autocontenido donde se pueda reproducir ese error que comentas.

Saludos,
José Luis Capel
User avatar
jlcapel
 
Posts: 229
Joined: Wed Oct 12, 2005 5:32 pm
Location: Valencia - España

Postby jllinas » Mon Apr 03, 2006 12:27 pm

Gracias José Luis,

Voy a construirlo, incluyendo la creación de la tabla y cuando lo tenga te lo envío.

Solo te enviaré el ejemplo, pues el resto de las clases modificadas por mi ya las tienes.

Gracias de nuevo,
Julio Llinás
Visita mi Blog en http://mangucybernetico.blogspot.com/
xHarbour 1.1.0 + FWH810 + Borland 5.5.1
User avatar
jllinas
 
Posts: 189
Joined: Fri Oct 14, 2005 12:33 am
Location: Santo Domingo, Dominican Republic

Julio como el link roto

Postby fsandoval » Mon Apr 03, 2006 7:23 pm

Julio como el link de las classes esta roto, no puedo hacer pruebas directas lo que te mande fue con la conversion de la tabla, por lo que comento que la tabla esta bien.


puedes subirlo a: ftp://proyectos.ita.mx
usuario:fer
pasword:fer

o enviamela por correo.

saludos
fernando snadoval ruiz
fernando sandoval ruiz
fsandoval@hotmail.com
fsandoval
 
Posts: 71
Joined: Mon Oct 10, 2005 9:24 pm
Location: aguascalientes

Postby Antonio Linares » Mon Apr 03, 2006 7:47 pm

Por favor, los ficheros que intercambieis alojadlos en www.hyperupload.com y publicar aqui el enlace de descarga para que asi otros usuarios puedan acceder a ellos. gracias.
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Postby jllinas » Fri Apr 07, 2006 11:02 am

Bueno, este es el final de este capitulo de la trilogía "ADO y yo" !

El asunto esta solucionado. Son tantas las consideraciones y aprendizajes con esto que me paso, que creo que estaré escribiendo algo mas amplio en mi recién abierto blog. Intentaré resumir aquí algunos puntos importantes para los "foronautas":

- Despues de buscar mucho entre las opciones para hacer el OPEN en el RS y en la conexion, confirmo que las mejores son las que aparecen en el ejemplo de JLC.

- El asunto estaba en la forma de "grabar" el registro en el recordset, que para los fines de la clase ADORS se trata de errores cometidos por mi en el método SAVE(). El grabar en el recordset es uno de los aspectos mas delicados que he encontrado en ADO.

- El mensaje que aparecia era consecuencia de que el RS se "cerraba" cuando se hacia una sustitucion que no le gustaba. Mucha luz me trajo a esto el nuevo amigo Fernando Sandoval, cuando me invitó a verificar el tipo de datos que quiero "grabar" y el tipo de datos de la columna que quiero que los acepte.

- El problema se concentraba en los campos tipo fecha. Intentaba escribir una fecha en un campo que el ADO lo interpretó como de tipo "indefinido". Lo descubrí haciendo VALTYPE( ::oRs:Fields("Fecha"):value ) sobre una fecha en blanco, pues me devolvía "U", mientras que cuando el registro tenía una fecha correcta, me devolvía "D". Fue entonces que, por sugerencia de FS evité realizar esta sustitución. Aun me falta probar un poco mas con este caso, pero ya está controlado.

- La otra cosa, fue la pregunta clave: "¿UPDATE o no UPDATE?".... pues cuando el registro no ha sido cambiado, no debe hacerse. JLC me sugirió en otra parte del foro una manera de realizarlo, pero no me funcionó, así que lo implementé localmente dentro del método SAVE(), y funciona perfectamente.

Estaré probando otras cosas durante la Semana Santa:

- manejo de campos MEMO (BLOB?, TEXT?)
- Generacion de reportes
- manejo de ADO por internet, etc.

Asi que por ahora, este capítulo lo considero cerrado. Estaré también publicando las clases modificadas de JLC en mi blog (http://mangucybernetico.blogspot.com/) para los que estén interesados, mas un ejemplo realizado por mi para demostrarme a mi mismo la potencia maravillosa del uso de ADO en todo esto.

Gracias a todos, en especial a JLC y FS por su paciencia, y sera hasta otro capítulo.

.... Y LA SAGA CONTINUA !!!!
Julio Llinás
Visita mi Blog en http://mangucybernetico.blogspot.com/
xHarbour 1.1.0 + FWH810 + Borland 5.5.1
User avatar
jllinas
 
Posts: 189
Joined: Fri Oct 14, 2005 12:33 am
Location: Santo Domingo, Dominican Republic


Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 37 guests