Есть ли способ использовать универсальный DbCommand для асинхронного обновления?
При использовании универсального DbCommand для выполнения обновления оно будет зависать бесконечно, если обновляемая строка заблокирована.
В качестве основного соединения используется поставщик Oracle Devart, Devart.Data.Oracle.OracleConnection.
Установка DbCommand.CommandTimeOut не имеет никакого эффекта, обновление никогда не прекращается.
DbCommand не реализует BeginExecuteNonQuery, поэтому, похоже, нет возможности использовать DbConnection/DbCommand в асинхронном режиме.
Я могу обойти это, используя OracleCommand Devart и BeginExecuteQuery, но это так.
Есть ли способ сделать это в общем виде?
Упрощенный код для специфической логики оракула:
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, по моему мнению, это ошибка в поставщике.
Можете ли вы выдать LOCK TABLE с опцией NOWAIT? Это немедленно вернет вам управление с ошибкой в случае сбоя блокировки. Например:
LOCK TABLE employees
IN EXCLUSIVE MODE
NOWAIT;
Есть несколько способов заблокировать стол. Вот раздел руководства разработчика по блокировке. Это страница справки по SQL для команды LOCK TABLE.
Другой вариант - использовать инструкцию SELECT .. FOR UPDATE NOWAIT, чтобы заблокировать строки, которые вы будете обновлять. Обе опции требуют, чтобы в Oracle были введены дополнительные команды помимо вашего оператора обновления.