OracleCommand timeout



OracleCommand.CommandTimeout的ODP.NET文档显示

默认值为0秒,不强制执行时间限制。

当指定的超时值在命令执行之前过期时完成后,命令尝试取消。如果取消如果成功,则引发异常,并显示消息ORA-0013:user请求取消当前操作。如果命令及时执行在没有任何错误的情况下,不会引发异常。

在多个OracleCommand对象使用相同对象的情况下连接,其中一个OracleCommand对象的超时过期可以终止在单个连接上的任何执行。制作OracleCommand的超时过期仅取消其自己的命令执行,只需为每个连接使用一个OracleCommandOracleCommand将CommandTimeout属性设置为大于0.

但像这样的代码有效:

static void Main(string[] args)
{
OracleConnection conn = null;
try
{
string connString =
"Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=myOracleHost)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=myServiceName)));User Id=system;Password=admin;Pooling = False;";
string cmdString1 = "UPDATE employee SET empname = 'temp1' where id = 1";
string cmdString2 = "Update employee set empname = 'temp2' where id = 2";
conn = new OracleConnection(connString);
var cmd1 = new OracleCommand(cmdString1, conn);
cmd1.CommandTimeout = 30;
var cmd2 = new OracleCommand(cmdString2, conn);
cmd2.CommandTimeout = 30;
conn.Open();
try
{
//Locked the row with ID 1 with an uncommitted update operation outside this code
cmd1.ExecuteNonQuery();
}
catch (Exception exception)
{
//Exception ORA-01013 Thrown as expected
}
try
{
//As per the documentation, this should not also work since this command object also uses the same connection as above and it timed out in the query above
cmd2.ExecuteNonQuery();
//But this still works fine. 
}
catch (Exception)
{
//no exception
}
}
finally
{
conn.Close();
}
}

我将同一个OracleConnection对象用于两个命令对象——cmd1cmd2,并且cmd1已经超时(正如预期的那样)。但是,根据文档,cmd2也不应该运行。但它仍然毫无例外地运行,并正确地更新了另一行。

您没有在连接上运行多个命令,而是有两个命令依次运行。当第一个命令超时时,连接上没有其他挂起的命令。在第一个命令成功或引发异常之后,代码才会提交第二个命令以供执行。

您引用的文档的最后一段应该是:在多个OracleCommand对象同时使用同一连接的情况下

static void Main(string[] args)
{
using (var conn = new OracleConnection("Pooling=False;...")) // why?
using (var cmd1 = conn.CreateCommand())
using (var cmd2 = conn.CreateCommand())
{
cmd1.CommandText = "UPDATE employee SET empname = 'temp1' WHERE id = 1";
cmd2.CommandText = "UPDATE employee SET empname = 'temp2' WHERE id = 2";
cmd1.CommandTimeout = 30;
cmd2.CommandTimeout = 30;
conn.Open();
// there are no commands on conn yet
try { cmd1.ExecuteNonQuery(); } // cmd1 is the only command on conn
catch (OracleException) { } // if timeout, no other command affected
// cmd1 is no longer on conn
try { cmd2.ExecuteNonQuery(); } // cmd2 is the only command on conn
catch (OracleException) { } // if timeout, no other command affected
// cmd2 is no longer on conn
}
}

最新更新