jguardon   02-05-2024, 18:56
#1
Hola a todos

Puede ser porque llevo bastante tiempo sin programar en gambas en plan serio, pero me encuentro con un problema que seguramente será una tontería y me tiene ya cabreado.

Tengo una función que realiza una consulta a la BD para listar los usuarios de una tabla. La tabla contiene usuarios de un sistema con su nombre, password, email, etc y contiene ahora mismo 3 usuarios. La función trata de devolver el resultado de la consulta en un array de colecciones, siendo cada elemento del array una colección con cada pareja de valor/campo correspondiente a cada campo. Hasta ahí, todo entendido, supongo.

El problema es que el array que devuelve la función siempre contiene los datos del último registro (usuario) repetido el número de veces igual al número de registros por alguna razón que ahora no soy capaz de entender. Este es el código, creo que se puede replicar fácilmente y depurar los resultados para ver lo que expongo.

Código:
    Dim hres As Result
    Dim cResult As New Variant[]
    Dim cRecord As New Collection

    If DBConn.connDB() Then
        hres = DBConn.hConn.Exec("SELECT * FROM ERP.users;")
        While hres.Available
            cRecord.Clear
            For Each sField As ResultField In hres.Fields
                cRecord.Add(hres[sField.Name], sField.Name)
            Next

            cResult.Add(cRecord)
            hres.MoveNext
        Wend

        Return cResult

    Endif

End

A ver si alguien me abre los ojos, porque ya me lloran de tando mirar...

Saludos

Por favor, usa el corrector ortográfico antes de pulsar el botón 'Enviar'
Shordi   02-05-2024, 22:33
#2
No uses clear. Recrea la colección en cada iteración del bucle.
While res...
Crecord=New collection
......
Perdón por los errores pero tecleo desde el teléfono y se me da fatal.

Slaudos

No podemos regresar
jguardon   03-05-2024, 17:13
#3
(02-05-2024, 22:33)Shordi escribió: Crecord=New collection

Pues claro! Qué tonto, estaba borrando el objeto en lugar de inicializar uno nuevo. Este tipo de errores son los que le ponen a uno en su sitio, jeje.

Gracias por iluminarme Angel

Así quedaría finalmente la función, que devuelve un array de colecciones en otra función que lo convierte a JSON como http response.
Código:
Public Function ListUsers() As Variant[]
     
    Dim hres As Result
    Dim cResult As New Variant[]
    Dim cRecord As Collection
     
    If DBConn.connDB() Then
        hres = DBConn.hConn.Exec("SELECT * FROM ERP.users;")
        While hres.Available
            cRecord = New Collection
            For Each sField As ResultField In hres.Fields
                cRecord.Add(hres[sField.Name], sField.Name)
            Next
  
            cResult.Add(cRecord)
            hres.MoveNext
        Wend
 
        Return cResult
     
    Endif
     
End

Por favor, usa el corrector ortográfico antes de pulsar el botón 'Enviar'
Shordi   03-05-2024, 22:29
#4
Aún así, hacer el clear antes de recrearla quizá evite problemas de memoria... No estoy seguro de qué hace el compilador con los elementos de la colección cuando la declaras como New Collection. Clear los destruye, por lo que quizá, para consultas grandes sea conveniente hacerlo primero.

Saludos

No podemos regresar
tincho   03-05-2024, 23:15
#5
(02-05-2024, 18:56)jguardon escribió: El problema es que el array que devuelve la función siempre contiene los datos del último registro

Es porque no la copias, las colecciones son direcciones de memoria y debes crear una nueva con copy por ejemplo
Código:
    Public Function ListUsers() As Variant[]
     
        Dim hres As Result
        Dim cResult As New Variant[]
        Dim cRecord As New Collection
     
        If DBConn.connDB() Then
            hres = DBConn.hConn.Exec("SELECT * FROM ERP.users;")
            While hres.Available
                cRecord.Clear
                For Each sField As ResultField In hres.Fields
                    cRecord.Add(hres[sField.Name], sField.Name)
                Next
                cResult.Add(cRecord.Copy())
                hres.MoveNext
            Wend
     
            Return cResult
     
        Endif
     
    End

Yo para no confundirme cuando escribo el código a las Variant[] les pongo nombre como oResult y a las colecciones les pongo cResult
Última modificación: 03-05-2024, 23:39 por tincho.

1 Saludo.
  
Usuarios navegando en este tema: 1 invitado(s)
Powered By MyBB, © 2002-2024 MyBB Group.
Made with by Curves UI.