我正在使用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驱动程序成功通过此测试。
答案 0 :(得分:2)
很明显,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 ms ORA-01013:用户请求取消当前操作
答案 1 :(得分:0)
您应该将ODP.NET客户端更新到4.121.1.0或更高版本。看起来CommandTimeout
在您的ODP.NET版本中不起作用。我刚刚在4.121.1.0上运行了Christian的测试,它只是起作用。我尝试了所有的Execute *操作,CommandTimeout
适用于所有这些操作。