2009-05-11 19 views
1

使用通用DbCommand执行更新时,如果正在更新的行被锁定,它将无限期地挂起。有没有办法使用通用DbCommand来执行异步更新?

使用的基本连接是Devart的Oracle提供,Devart.Data.Oracle.OracleConnection

设置DbCommand.CommandTimeOut没有任何效果可言,更新永不超时。

DbCommand没有实现BeginExecuteNonQuery,所以似乎没有办法以异步的方式使用DbConnection/DbCommand。

我能够通过使用Devart的OracleCommand和BeginExecuteQuery来解决这个问题,但它确实如此。

有没有办法以通用的方式做到这一点?

为Oracle特定的逻辑简化代码:

public bool TestAsyncUpdateRowOracle(string key, OracleConnection con, string sql) 
{ 
    const int timoutIterations=10; 
    bool updateOk=false; 
    OracleCommand cmd = new OracleCommand(sql, con); 
    cmd.Parameters.Add(Util.CreateParameter(dbSrcFactory, DbType.String, 16, "key")); 
    cmd.CommandType = CommandType.Text; 
    cmd.Parameters[0].Value = key.ToString(); 

    IAsyncResult result = cmd.BeginExecuteNonQuery(); 
    int asyncCount = 0; 
    while (!result.IsCompleted) 
    { 
     asyncCount++; 
     if (asyncCount > timeoutIterations) 
     { 
      break; 
     } 
     System.Threading.Thread.Sleep(10); 
    } 

    if (result.IsCompleted) 
    { 
     int rowsAffected = cmd.EndExecuteNonQuery(result); 
     Console.WriteLine("Done. Rows affected: " + rowsAffected.ToString()); 
    } 
    else 
    { 
     try 
     { 
      cmd.Cancel(); 
      Console.WriteLine("Update timed out, row is locked"); 

     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
      Console.WriteLine("Unable to cancel update"); 
     } 
    } 
    cmd.Dispose(); 
} 

回答

2

不幸的是,没有在ADO.NET中有异步操作的接口或基类(例如BeginExecuteNonQuery/EndExecuteNonQuery)。它们仅在极少数ADO.NET提供程序实现中出现。 (SqlClient,Devart Oracle)。

也就是说,如果在设置CommandTimeOut时没有超时,我认为这是提供程序中的错误。

0

可以发出与NOWAIT选项LOCK TABLE?如果锁定失败,这将立即返回控制给您的错误。例如:

LOCK TABLE employees 
    IN EXCLUSIVE MODE 
    NOWAIT; 

有几种锁定表的方法。 Here是关于锁定的开发人员指南部分。 This是LOCK TABLE命令的SQL参考页面。

另一种选择是使用SELECT .. FOR UPDATE NOWAIT语句锁定要更新的行。除了您的更新声明外,这两个选项都需要向Oracle发布其他命令。

相关问题