Reputation: 712
I'm trying to fill a DataSet object with an OracleCommand object, I just started using Oracle, I've using SQL Server all my life. On my NET console project I added the NuGet Oracle.ManagedDataAccess package and changed Sql objects to Oracle. Like: SqlConnection to OracleConnection. In SQL Server it works perfectly, but in Oracle it gives me this error I don't really understand what it means.
I changed SqlConnection
to OracleConnection
and SqlCommand
to OracleCommand
also
command.Parameters.AddWithValue("@" + parameters[i], values[i] ?? DBNull.Value);
to
command.Parameters.Add(parameters[i], values[i] ?? DBNull.Value);
command.Parameters[i].Value = values[i];
Because AddWithValue
doesn't exist on OracleCommand
This is the method that gets the data from the db.
private void GetData(string storedProcedure, IReadOnlyList<string> parameters, IReadOnlyList<object> values)
{
using (var connection = new OracleConnection(_connectionString))
{
using (
var command = new OracleCommand(storedProcedure, connection)
{
CommandType = CommandType.StoredProcedure
})
{
if (parameters != null)
for (var i = 0; i < parameters.Count; i++)
{
command.Parameters.Add(parameters[i], values[i] ?? DBNull.Value);
}
var ds = new DataSet();
connection.Open();
new OracleDataAdapter(command).Fill(ds);
_data = ds.Tables;
connection.Close();
}
}
}
These are the parameters im using.
var db = new Connector.Provider("AIA.GET_DATA",
new[]{
"Test1",
"Test2",
"Test3",
"Test4"},
new object[]{
1,
2,
3,
null});
And this is the stored procedure.
PROCEDURE GET_DATA(
Test1 in NUMBER,
Test2 in NUMBER,
Test3 in NUMBER,
Test4 in NUMBER,
TestOut out SYS_REFCURSOR
);
On the constructor of Provider it gets the connection string and uses method GetData.
It fails on:
new OracleDataAdapter(command).Fill(ds);
Oracle.ManagedDataAccess.Client.OracleException: 'ORA-03115: unsupported network datatype or representation'
Again, this works perfectly on SQL Server.
Any help is appreciated, at least, what does this error message means.
EDIT:
Thank you Luke Woodward, that was very helpful. So there was a problem with the OUT parameter, but also with the type of the parameters I was sending. So that solves the problem.
Anyway, I ended up with this new method. Which is working fine, except with nulls.
private void GetData(string storedProcedure, IReadOnlyList<string> parameters, IReadOnlyList<object> values, IReadOnlyList<string> cursors)
{
using (var connection = new OracleConnection(_connectionString))
{
using (
var command = new OracleCommand(storedProcedure, connection)
{
CommandType = CommandType.StoredProcedure
})
{
if (parameters != null)
for (var i = 0; i < parameters.Count; i++)
{
var parameter = new OracleParameter();
parameter.ParameterName = parameters[i];
if (values[i] is Enum)
parameter.Value = (int)values[i];
else
parameter.Value = values[i];
if (cursors != null && cursors.Contains(parameter.ParameterName))
{
parameter.Direction = ParameterDirection.Output;
parameter.OracleDbType = OracleDbType.RefCursor;
}
else
{
parameter.OracleDbType = GetOracleType(values[i]);
}
command.Parameters.Add(parameter);
}
var ds = new DataSet();
connection.Open();
new OracleDataAdapter(command).Fill(ds);
_data = ds.Tables;
connection.Close();
}
}
}
In Sql I could use DBNull.Value
, but in Oracle I need to define OracleDbType
, which is anonoying since this method worked for any object, not caring about the type, now I still don't know how to fix it to make it work with any object in Oracle. But that could be considered offtopic, this question could be marked as answered.
Upvotes: 1
Views: 2062
Reputation: 64949
You need to add an OracleParameter
for the OUT
parameter TestOut
but you are not doing this.
Add these lines after the other lines that set up the parameters:
var outParam = new OracleParameter("TestOut", OracleDbType.RefCursor, ParameterDirection.Output);
command.Parameters.Add(outParam);
You will then need to execute the command separately rather than pass the command to the OracleDataAdapter
. Do this by adding the line
command.ExecuteNonQuery();
immediately after the two that add outParam
.
Finally, fill the dataset from the ref cursor in the OUT
parameter by replacing the line
new OracleDataAdapter(command).Fill(ds);
with
new OracleDataAdapter().Fill(ds, (OracleRefCursor)outParam.Value);
Incidentally, I got a different error when I ran your code. I got the error PLS-00306: wrong number or types of arguments in call to 'GET_DATA'
.
Upvotes: 1