I'm currently evaluating Oracle's ODP.NET DataProvider and I ran into a problem that popped up in one of our testcases: When the same command text is executed with different parameter types, the parameter type of the first executed command is used in all following commands.
Take for example the following code:
const int sampleInt32 = 1234567890;
const string sampleNvarchar = "someTestString";
const string sqlCommandtext = "SELECT :PARAM PARAM FROM DUAL";
using (OracleConnection connection = new OracleConnection(builder.ConnectionString))
{
connection.Open();
//Test 1 - Int 32
using (OracleCommand commandInt32 = connection.CreateCommand())
{
commandInt32.CommandText = sqlCommandtext;
commandInt32.Parameters.Add("PARAM", OracleDbType.Int32, sampleInt32, ParameterDirection.Input);
using (IDataReader reader = commandInt32.ExecuteReader())
{
while (reader.Read())
{
int resultInt32 = (int)reader.GetDecimal(0);
Assert.AreEqual(sampleInt32, resultInt32);
}
}
}
//Test 2 - NVarchar
using (OracleCommand commandNVarchar = connection.CreateCommand())
{
commandNVarchar.CommandText = sqlCommandtext;
commandNVarchar.Parameters.Add("PARAM", OracleDbType.NVarchar2, sampleNvarchar, ParameterDirection.Input);
using (IDataReader reader = commandNVarchar.ExecuteReader())
{
while (reader.Read())
{
string resultNVarchar = reader.GetString(0);
Assert.AreEqual(sampleNvarchar, resultNVarchar);
}
}
}
}
If commandInt32 is executed before commandNVarchar, execution of commandNVarchar fails with ORA-01722 - Invalid number. If the order is switched so commandNVarchar is executed first, it fails with "Specified cast is not valid" on reader.GetDecimal.
So far I've tried setting StatementCacheSize=0; Pooling=false; StatementCachePurge=true as ConnectionString parameters but I can't get this to work.
Is there anything I'm missing or are there any other options worth trying?
EDIT: Maybe some background on why this is needed/required: We don't use ODP or any other Dataprovider directly in our application (or at least: we're on our way to reach this goal), there's an DataLayer in between that performs database/provider specific optimiziations and monitoring of connection health,...
In this Layer for example StoredProcedures can be called, having the option of parameter type tuning. Some of our procedures have Clobs as Parameter types, as sometimes the value can be longer than x characters, but most likely it will be shorter. So before executing via ExecuteNonQuery with ArrayBindCount set to y, parameter values are checked if Clob can be passed as varchar (Nclob as Nvarchar). "Rebinding" reduces the time to execute 2500 records from about 500ms to 200ms at the cost of losing a few ms checking string lengths. And this rebinding can only be done if the parameter type can be changed. Without this option we would need to execute it as Clob everytime, taking the performance hit.