Есть ли способ использовать универсальный DbCommand для асинхронного обновления? - PullRequest
1 голос
/ 11 мая 2009

При использовании универсального 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 ]

2 голосов
/ 16 сентября 2010

К сожалению, нет, в ADO.NET нет интерфейса или базового класса с асинхронными операциями (например, BeginExecuteNonQuery / EndExecuteNonQuery). Они присутствуют только в очень немногих реализациях поставщика ADO.NET. (SqlClient, Devart Oracle).

Тем не менее, если не установлен тайм-аут при установке CommandTimeOut, по моему мнению, это ошибка в поставщике.

0 голосов
/ 11 мая 2009

Можете ли вы выдать LOCK TABLE с опцией NOWAIT? Это немедленно вернет вам управление с ошибкой в ​​случае сбоя блокировки. Например:

LOCK TABLE employees
   IN EXCLUSIVE MODE 
   NOWAIT; 

Есть несколько способов заблокировать стол. Здесь - раздел руководства разработчика по блокировке. - страница справочника по SQL для команды LOCK TABLE.

Другой вариант - использовать инструкцию SELECT .. FOR UPDATE NOWAIT для блокировки строк, которые вы будете обновлять. Обе опции требуют, чтобы в Oracle помимо команд оператора обновления были введены дополнительные команды.

...