我目前正在评估 Oracle 的 ODP.NET DataProvider,我遇到了一个在我们的一个测试用例中弹出的问题:当使用不同的参数类型执行相同的命令文本时,第一个执行命令的参数类型将用于以下所有内容命令。
以下面的代码为例:
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);
}
}
}
}
如果 commandInt32 在 commandNVarchar 之前执行,则 commandNVarchar 的执行失败并出现 ORA-01722 - 无效编号。如果切换了顺序,因此首先执行 commandNVarchar,它会失败,并在 reader.GetDecimal 上显示“Specified cast is not valid”。
到目前为止,我已经尝试设置 StatementCacheSize=0; 池化=假;StatementCachePurge=true 作为 ConnectionString 参数,但我无法让它工作。
有什么我遗漏的,还是有其他值得尝试的选择?
编辑:也许需要/需要一些背景知识:我们不直接在我们的应用程序中使用 ODP 或任何其他 Dataprovider(或者至少:我们正在实现这个目标),在这之间有一个 DataLayer执行数据库/提供商特定的优化和连接健康监控,...
例如,在这一层中,可以调用 StoredProcedures,具有参数类型调整的选项。我们的一些程序将 Clob 作为参数类型,因为有时值可能比 x 个字符长,但很可能会更短。因此,在通过 ArrayBindCount 设置为 y 的 ExecuteNonQuery 执行之前,检查参数值是否可以作为 varchar 传递(Nclob 作为 Nvarchar)。“重新绑定”将执行 2500 条记录的时间从大约 500 毫秒减少到 200 毫秒,代价是损失了几毫秒的检查字符串长度。而这种重新绑定只有在参数类型可以改变的情况下才能完成。如果没有此选项,我们将需要每次都将其作为 Clob 执行,从而降低性能。