El problema tiene dos partes y al menos dos formas de enfrentarlo.
Por un lado, estás usando el mismo objeto para realizar dos lecturas sin que la primera se haya cerrado, ya que la conexión se abre una sola vez y en esa conexión se crea un objeto DataReader que estás leyendo... cuando mandas a abrir nuevamente un DataReader...
En principio, hay un conflicto. O Creas una copia de ese DataReader, o las lecturas deberán se consecutivas y no anidadas.
Esa sería la primera opción
Esa solución (la que tu propones) a mí no me convence, porque resulta en un ciclo innecesario: No necesitas crear dinámicamente la tabla, que la misma consulta ya te está devolviendo.
Es decir: La consulta que enviaste ya te devolvió una tabla. ¿Para qué crear dinámicamente una, si lo que necesitas es tomar los valores que ya te devolvió?
La idea es que en lugar de que la función devuelva un DataReader, ¿por qué no te devuelve directamente la tabla? SI el problema es que te devuelve más columnas de las que necesitas, o bien las eliminas después de leer la tabla, o no se las pides...
Por otro lado, Leer una tabla entera permitiría la misma creación dinámica que actualmente usas, sin el problema de la duplicidad de lectores...
Esto:
Código MySQL:
Ver originalPublic
Function consultar
(ByVal orden
As String
) As DataTable
abrir()
Dim oTabla
as new DataTable
Dim cmd
As New SqlCommand
(orden
, con
) Dim oRead
as New SqlDataReader
(cmd
) oRead.Fill(oTabla)
Return oTabla.Copy()
te devolvería una copia de tabla, recibiendo el mismo parámetro. Como las lecturas subsecuentes serían sobre un objeto DataTable, no crearían ningún conflicto.
Un tip final: Yo no le veo razón a crear dinámicamente una tabla, columna a columna, celda a celda, cuando ya conoces sus dimensiones y tipos de datos reales.
¿Por qué no creas directamente la tabla con todas sus columnas y simplemente cargas los registros? Tal y como la planteas, no estás ganando nada al hacerlo así.