是否可以使用ADO.NET锁定oracle 10g数据库表?

时间:2010-03-05 11:41:39

标签: c# ado.net oracle10g

我有一个表,其中包含需要由多个程序获取和设置的最大值。当获得旧值并在C#中更新new时,如何锁定表一段时间?换句话说:

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 个答案:

答案 0 :(得分:2)

Oracle可以自己处理locking。尝试尽可能使用数据库功能。

Sequence是Oracle中的首选方式,因为上面的评论会告诉您。

答案 1 :(得分:2)

将提供程序用于指定的数据库通常是一种很好的做法。 Oracle在他的网站上有一个专门的Microsoft.Net提供商,我建议使用它。请注意,所有专用提供程序都实现相同的基本classess,因此保留了一定的抽象级别。其次,U肯定需要交易。我建议通过调用存储过程(通过executeNonQuery()或executeScalar()方法)来实现,具体取决于U需要的结果。

如果您无法使用存储过程(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 :(得分:1)

听起来你应该使用Oracle Sequence - 正如我在评论中已提到的那样:)

每当调用NEXTVAL时,它都会返回唯一的数字。


如果由于某种原因你无法使用序列,只需在该行上执行UPDATE即可。在您结束事务(COMMITROLLBACK)之前,Oracle将锁定该行,并且所有其他更新将等到锁定被释放。


修改

如果ADO不支持交易,您也可以使用AUTONOMOUS_TRANSACTION将其放入Oracle程序中:

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,锁定会被释放,而您自己的交易不会受到影响。

答案 3 :(得分:0)

有一个锁定表命令

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

注意:在结束交易之前,您无法重置锁定。因此,如果您锁定了桌子,则无法解锁。

答案 4 :(得分:0)

要在获取它的语句之后保持锁定,您需要一个事务。

答案 5 :(得分:-1)

您可以尝试其他方法。首先在表上启用表锁定。说我的桌子是T。然后

SQL> alter table t enable table lock   
2    /

现在,你可以选择,任何其他选择都会等待,因为你有一个锁。

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

因此,任何其他会话中的select命令都不会返回并等待释放锁。请记住,您需要执行COMMIT才能解除锁定。