Siéntete en la libertad de compartir nuestros tutoriales y códigos en tus redes, apóyanos para hacer crecer esta comunidad.
Solución:
El principal problema con su código era que no establecía el tamaño de enlace para cada elemento de su búfer de salida. Además, no indexaba correctamente el búfer de salida al recuperar los resultados. Y finalmente, el orden de ejecución también juega un papel: primero debe habilitar su salida antes de ejecutar su bloque de código anónimo. Cada uno de los cambios realizados se comenta en el siguiente MCVE. Solo se realizaron los cambios necesarios para que funcione.
static void Main(string[] args)
lvsName); END;";
OracleConnection _connection = new OracleConnection(str);
try
_connection.Open();
//adapter not being used
//using (OracleDataAdapter oda = new OracleDataAdapter())
using (OracleCommand cmd = new OracleCommand(sql, _connection))
// First enable buffer output
// Set output Buffer
cmd.CommandText = "BEGIN DBMS_OUTPUT.ENABLE(NULL); END;";
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
// Then execute anonymous block
// Execute anonymous PL/SQL block
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
var res = cmd.ExecuteNonQuery();
// Get output
cmd.CommandText = "BEGIN DBMS_OUTPUT.GET_LINES(:outString, :numLines); END;";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Clear();
cmd.Parameters.Add(new OracleParameter("outString", OracleDbType.Varchar2, int.MaxValue, ParameterDirection.Output));
cmd.Parameters["outString"].CollectionType = OracleCollectionType.PLSQLAssociativeArray;
cmd.Parameters["outString"].Size = sql.Length;
cmd.Parameters["outString"].ArrayBindSize = new int[sql.Length];
// set bind size for each array element
for (int i = 0; i < sql.Length; i++)
cmd.Parameters["outString"].ArrayBindSize[i] = 32000;
cmd.Parameters.Add(new OracleParameter("numLines", OracleDbType.Int32, ParameterDirection.InputOutput));
cmd.Parameters["numLines"].Value = 10; // Get 10 lines
cmd.ExecuteNonQuery();
int numLines = Convert.ToInt32(cmd.Parameters["numLines"].Value.ToString());
string outString = string.Empty;
// Try to get more lines until there are zero left
while (numLines > 0)
for (int i = 0; i < numLines; i++)
// use proper indexing here
//OracleString s = (OracleString)cmd.Parameters["outString"].Value;
OracleString s = ((OracleString[])cmd.Parameters["outString"].Value)[i];
outString += s.ToString();
// add new line just for formatting
outString += "rn";
cmd.ExecuteNonQuery();
numLines = Convert.ToInt32(cmd.Parameters["numLines"].Value.ToString());
Console.WriteLine(outString);
catch (Exception ex)
Console.WriteLine(ex.ToString());
_connection.Close();
_connection.Dispose();
Console.WriteLine("Press RETURN to exit.");
Console.ReadLine();
Y el resultado de salida es:
Do you see me?
My name is: Oracle
Press RETURN to exit.
Gracias por la respuesta anterior de jsanalytics, que proporcionó una buena base para una solución. Sin embargo, existen algunos problemas con la solución anterior, principalmente relacionados con el uso de sql.Length en muchos lugares donde no tiene sentido. Aquí hay una solución reutilizable que corrige algunos de los problemas.
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
namespace MyNamespace
public static class DbmsOutputHelper
public const int DefaultReadBatchSize = 10;
public static void EnableDbmsOutput(this OracleConnection conn)
using (var cmd = conn.CreateCommand())
cmd.CommandText = "DBMS_OUTPUT.ENABLE";
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
public static void DisableDbmsOutput(this OracleConnection conn)
using (var cmd = conn.CreateCommand())
cmd.CommandText = "DBMS_OUTPUT.DISABLE";
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
public static List ReadDbmsOutput(this OracleConnection conn, int readBatchSize = DefaultReadBatchSize)
if (readBatchSize <= 0)
throw new ArgumentOutOfRangeException(nameof(readBatchSize), "must be greater than zero");
using (var cmd = conn.CreateCommand())
cmd.CommandText = "DBMS_OUTPUT.GET_LINES";
cmd.CommandType = CommandType.StoredProcedure;
var linesParam = cmd.Parameters.Add(new OracleParameter("lines", OracleDbType.Varchar2, int.MaxValue, ParameterDirection.Output));
linesParam.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
linesParam.Size = readBatchSize;
linesParam.ArrayBindSize = Enumerable.Repeat(32767, readBatchSize).ToArray(); // set bind size for each array element
var numLinesParam = cmd.Parameters.Add(new OracleParameter("numlines", OracleDbType.Int32, ParameterDirection.InputOutput));
var result = new List();
int numLinesRead;
do
numLinesParam.Value = readBatchSize;
cmd.ExecuteNonQuery();
numLinesRead = ((OracleDecimal)numLinesParam.Value).ToInt32();
var values = (OracleString[])linesParam.Value;
for (int i = 0; i < numLinesRead; i++)
result.Add(values[i].ToString());
while (numLinesRead == readBatchSize);
return result;
Me parece que lo estás haciendo en el orden incorrecto ...
// Execute anonymous PL/SQL block
cmd.CommandType = CommandType.Text;
var res = cmd.ExecuteNonQuery();
// Set output Buffer
cmd.CommandText = "BEGIN DBMS_OUTPUT.ENABLE(NULL); END;";
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
// Get output
cmd.CommandText = "BEGIN DBMS_OUTPUT.GET_LINES(:outString, :numLines); END;";
Entre configurar (habilitar) el DBMS_OUTPUT
y obteniendo la salida usando GET_LINES
debería ser su comando de escritura, pero en cambio, es lo primero que está ejecutando.
Intente cambiar el orden. Avíseme si funciona porque no lo probé (no estoy acostumbrado a C # ... lo tengo en Java).
Aquí puedes ver las reseñas y valoraciones de los lectores
Si para ti ha resultado de ayuda este post, sería de mucha ayuda si lo compartieras con el resto entusiastas de la programación de este modo nos ayudas a extender esta información.