gpt4 book ai didi

oracle - ODP.NET 托管驱动程序在命令超时的情况下不返回控制权

转载 作者:行者123 更新时间:2023-12-01 14:12:20 25 4
gpt4 key购买 nike

我正在使用 ODP.NET 托管驱动程序 12.1.0.2.1(ODAC 12c 第 3 版)并发现了严重错误。如果在命令执行期间超时导致连接池中的线程和连接丢失。

这个测试总是失败:

[TestMethod]
[ExpectedException(typeof (Oracle.ManagedDataAccess.Client.OracleException))]
[Timeout(70000)]
public void OracleCommandTimeoutTest()
{
const string connectionString =
"user id=user;password=pass;data source=192.168.1.1:1521\db";
using (var connection = new Oracle.ManagedDataAccess.Client.OracleConnection(connectionString))
using (var command = connection.CreateCommand())
{
// we need for 60 seconds timeout
command.CommandTimeout = 60; //default value is 0 (unlimited)
//here can be any query that takes longer time than specified in CommandTimeout
command.CommandText = "execute DBMS_LOCK.sleep(70)";
connection.Open();
//this statement will never return control
command.ExecuteNonQuery();
//BUG:connection and command never be disposed and test will be fail after timeout
}
}

让我们看看内部驱动程序。查找功能:

internal void ReceiveExecuteResponse

该函数处理异常(ORA 03111)并在此处调用 Reset():

catch (NetworkException ex)
{
if (ex.ErrorCode != 3111)
throw;
else
this.m_marshallingEngine.m_oracleCommunication.Reset();
}

在将 URG 数据包发送到 Oracle 数据库并读取应答功能后,将进入永不结束的循环:

while (!flag1)
{

函数尝试读取响应流,直到 AppDomain 被卸载。在修复此错误之前,我们无法使用托管驱动程序。非托管 x64 驱动程序成功通过此测试。

最佳答案

很明显,OP 不小心使用了 MS OracleClient。它确实适用于 ODP.NET。

工作示例:

public static void OracleCommandTimeoutTest()
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
try
{
const string connectionString = @"user id=scott;password=tiger;data source=inst1";
using (var connection = new OracleConnection(connectionString))
using (var command = connection.CreateCommand())
{
// we need for 60 seconds timeout
command.CommandTimeout = 20; //default value is 0 (unlimited)

//here can be any query that takes longer time than specified in CommandTimeout
command.CommandText = "BEGIN DBMS_LOCK.sleep(70); END;";
connection.Open();

//this statement will never return control
sw.Start();
command.ExecuteNonQuery();
sw.Stop();

Console.WriteLine("ExecuteNonQuery Completed (Didn't timeout): " + sw.Elapsed + " ms");
//BUG:connection and command never be disposed and test will be fail after timeout
}
}
catch (Exception ex)
{
sw.Stop();

Console.WriteLine();
Console.WriteLine("Timed-Out after: " + sw.Elapsed + " ms");
Console.WriteLine(ex.Message);
}
}

上面的测试用例给出了以下结果:

超时时间:00:00:21.0581601 毫秒ORA-01013: 用户请求取消当前操作

关于oracle - ODP.NET 托管驱动程序在命令超时的情况下不返回控制权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29285609/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com