Можно ли заблокировать таблицу базы данных Oracle 10g с ADO.NET? - PullRequest
1 голос
/ 05 марта 2010

У меня есть таблица, которая содержит максимальное значение, которое необходимо получить и установить несколькими программами. Как я могу заблокировать таблицу на некоторое время, когда получено старое значение и обновлено новое в C #? Другими словами:

string sql = "lock table MaxValueTable in exclusive mode";  
using (DbCommand cmd = cnctn.CreateCommand())
{
    cmd.CommandText = sql;
    // execute command somehow!!
}

maxValue = GetMaxValue();
SetMaxValue(maxValue + X);

sql = "lock table MaxValueTable in share mode";  
using (DbCommand cmd = cnctn.CreateCommand())
{
    cmd.CommandText = sql;
    // execute command somehow!!
}

Ответы [ 6 ]

2 голосов
/ 15 марта 2010

Обычно рекомендуется использовать провайдеров для указанной базы данных.У Oracle на сайте есть специальный провайдер для Microsoft.Net, я бы порекомендовал его использовать.Обратите внимание, что все выделенные провайдеры реализуют один и тот же базовый класс, поэтому сохраняется определенный уровень абстракции.Во-вторых, вам определенно нужна транзакция.Я бы порекомендовал сделать это, вызвав хранимую процедуру (либо с помощью методов executeNonQuery () или executeScalar () - в зависимости от результата, который вам нужен.

Если вы не можете использовать хранимые процедуры (U не может создатьзатем) Вы должны использовать переводы, предлагаемые провайдером. Как провайдер Ole, так и провайдер ORacle предлагают транзакцию

using (Transaction t = cnctn.BeginTransation())


`//set some options like timeout, use serialization level like //Serializable in .Net TransactionScope


   {
        string sql = "lock table MaxValueTable in exclusive mode";
        using (DbCommand cmd = cnctn.CreateCommand())
        { 
           cmd.CommandText = sql;
           cmd.ExecuteNonQuery();
          // execute command somehow!! 
        } 
       maxValue = GetMaxValue();
       SetMaxValue(maxValue + X);
       //I presume U need to update the value in the table so some Update would be nice
       sql = "lock table MaxValueTable in share mode";
       using (DbCommand cmd = cnctn.CreateCommand())
       { 
           cmd.CommandText = sql;
           cmd.ExecuteNonQuery();
           // execute command somehow!! 
       }
       cnctn.Commit();
  }
  catch(SQLException e)
  {
     //log whatever, gracefully handle things
     t.Rollback();
     //throw;?
  }
  finally
  {
        cntn.close();
  }
2 голосов
/ 05 марта 2010

Oracle может обрабатывать блокировку сама. Постарайтесь использовать возможности базы данных, насколько это возможно.

Последовательность является предпочтительным способом в Oracle, как приведено в комментариях выше.

1 голос
/ 05 марта 2010

Похоже, вы должны использовать вместо Oracle Sequence - как уже упоминалось в моем комментарии:)

Он будет возвращать уникальные номера при вызове NEXTVAL.


Если по какой-то причине вы не можете использовать последовательность, просто выполните UPDATE в этой строке. Oracle будет блокировать эту строку до тех пор, пока вы не завершите транзакцию (COMMIT или ROLLBACK), а все остальные обновления будут ожидать снятия блокировки.


EDIT

Если транзакции не поддерживаются в ADO, вы также можете поместить это в процедуру Oracle, используя AUTONOMOUS_TRANSACTION:

CREATE OR REPLACE PROCEDURE allocate_sequence_numbers(
  in_size IN max_value_table.val%TYPE,
  out_next_sequence_number OUT max_value_table.val%TYPE
)
AS
  PRAGMA AUTONOMOUS_TRANSACTION;
  next_sequence_number max_value_table.val%TYPE;
BEGIN
  UPDATE max_value_table
  SET val = val + in_size
  RETURNING val - in_size
  INTO out_next_sequence_number;
  COMMIT;
END allocate_sequence_numbers;

Он обновит вашу таблицу, чтобы «распределить» указанное количество значений, и вернет первое число последовательности, которую вы распределили. Следующее приложение, которое вызывает его, получит следующий порядковый номер.

UPDATE вызывает блокировку в этой строке, поэтому другие вызовы должны ждать, пока эта блокировка не будет снята. При использовании COMMIT внутри AUTONOMOUS_TRANSACTION блокировка снимается, в то время как на вашу собственную транзакцию это не повлияет.

0 голосов
/ 05 марта 2010

Вы можете попробовать другой метод. Сначала включите блокировку таблицы на столе. Скажи, что мой стол T. Тогда

SQL> alter table t enable table lock   
2    /

Теперь вы можете выбирать, и любой другой выбор будет ждать, потому что у вас есть блокировка.

SQL> select *
  2  from t
  3  for update
  4  /

Таким образом, любая команда выбора в другом сеансе не будет возвращаться и будет ждать снятия блокировки. Помните, вам нужно сделать COMMIT, чтобы снять блокировку.

0 голосов
/ 05 марта 2010

Чтобы сохранить блокировку после оператора, который его принимает, необходима транзакция.

0 голосов
/ 05 марта 2010

Есть команда блокировки таблицы

LOCK TABLE [schema.] table IN lockmode EXCLUSIVE [NOWAIT]

Примечание: вы не можете сбросить блокировку, пока не завершите транзакцию. Поэтому, если вы заблокировали стол, вы не сможете его разблокировать.

...