2009-05-11 54 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發佈其他命令。

相關問題