ODP.NET:参数类型“缓存”在相同的 CommandText 上

Lin*_*nky 5 c# ado.net odp.net

我目前正在评估 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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果在 commandNVarchar 之前执行 commandInt32,则 commandNVarchar 的执行将失败,并显示 ORA-01722 - 数字无效。如果顺序被切换,commandNVarchar 首先执行,则它会失败,并在 reader.GetDecimal 上显示“指定的转换无效”。

到目前为止,我已经尝试设置 StatementCacheSize=0; 池化=假;StatementCachePurge=true 作为 ConnectionString 参数,但我无法让它工作。

我有什么遗漏的或者还有其他值得尝试的选择吗?

编辑:也许有一些关于为什么需要/要求这样做的背景:我们不直接在我们的应用程序中使用ODP或任何其他数据提供者(或者至少:我们正在实现这个目标),中间有一个数据层执行数据库/提供商特定的优化和连接健康状况的监控,...

在此层中,可以调用例如 StoredProcedures,并具有参数类型调整的选项。我们的一些过程将 Clob 作为参数类型,因为有时该值可能比 x 个字符长,但很可能会更短。因此,在通过将 ArrayBindCount 设置为 y 的 ExecuteNonQuery 执行之前,会检查参数值是否可以作为 varchar 传递(Nclob 作为 Nvarchar)。“重新绑定”将执行 2500 条记录的时间从大约 500 毫秒减少到 200 毫秒,但代价是检查字符串长度时损失了几毫秒。并且只有当参数类型可以改变时才能进行这种重新绑定。如果没有这个选项,我们每次都需要将其作为 Clob 执行,从而影响性能。

Vad*_* K. 3

据我了解,列表中不支持参数绑定SELECT。我非常惊讶这竟然有效,以至于我必须运行你的代码才能亲眼看到它。我相信对于客户端来说允许该 SQL 语句执行根本就是一个错误。

无论如何,我在测试用例之间插入了以下行以使它们都正常工作:

connection.PurgeStatementCache();
Run Code Online (Sandbox Code Playgroud)

但是,这似乎仅适用于托管客户端(我已尝试使用版本 4.112.3.60)。正如您所描述的,常规客户端仍然失败。