代码:
    OracleConnection myConnection = new OracleConnection(System.Configuration.ConfigurationSettings.AppSettings["DBConnection"]);
    OracleCommand selectCommand = new OracleCommand("SELECT autoid FROM sq  WHERE (tablename = :tablename for update) ", myConnection);
    OracleCommand updateCommand = new OracleCommand("UPDATE sq SET autoid = autoid + 1 WHERE (tablename = :tablename)", myConnection);
    OracleCommand insertCommand = new OracleCommand("INSERT INTO sq (tablename, autoid) VALUES (:tablename, 0)", myConnection);    selectCommand.Parameters.Add(":tablename", OracleType.NVarChar, 32);
    updateCommand.Parameters.Add(":tablename", OracleType.NVarChar, 32);
    insertCommand.Parameters.Add(":tablename", OracleType.NVarChar, 32);    myConnection.Open();
    OracleTransaction myTrans = myConnection.BeginTransaction();    selectCommand.Transaction = myTrans;
    updateCommand.Transaction = myTrans;
    insertCommand.Transaction = myTrans;
    try
    {
        selectCommand.Parameters[":tablename"].Value = TableName;
        updateCommand.Parameters[":tablename"].Value = TableName;
        insertCommand.Parameters[":tablename"].Value = TableName;        OracleDataReader myReader = selectCommand.ExecuteReader();
        if (myReader.HasRows)
        {
             myReader.Read();
             r = myReader.GetInt32(0);
             r++;
             myReader.Close();
         }
        else
        {
             myReader.Close();
             insertCommand.ExecuteNonQuery();
             r = 1;
         }         updateCommand.ExecuteNonQuery();
         myTrans.Commit();
    }代码一大堆,其实逻辑还是很简单,主要作用就是从数据库的表里面取名为tablename的id,这个id是取一次+1,但绝对不能重复,否则应用会出问题。
    表sq,有两个字段,一个是tablename,一个是autoid,其中tablename表示我所要取的项目,autoid就是我要取的值了。如果sq里面没有对应tablename的项目,autoid为1并作为返回值,并将该项目插入sq,如果有tablename对应的项目,则直接取autoid+1返回,同时UPDATE autoid=autoid+1。
   现在的问题是,我用了事物来控制,可是有没有办法控制这个事物begin的时候,别的会话不允许访问sq对应的tablename的项目?否则是很有可能造成多个会话同时取到同一个autoid的情况,那样应用不允许。
    请各位大神不吝赐教!!!

解决方案 »

  1.   

    如果你那ID只是个唯一标示不是用来显示的话,最后不那样,直接用Guid.NewGuid()来做唯一标示。。
      

  2.   

    如果不考虑用表来处理的话,那用oracle的sequence是最好的了。方便,也不用操心这些并发的问题。要考虑代码统一,多个数据库兼容,只能采取这种办法了。
      

  3.   

    嘿嘿。刚测试了一下,貌似transactionbegin后,别的session就没法访问对应的表了?必须等前面的session transaction结束后才能读取和操作?我就在一台机器上测试的,开了两个网页,应该没问题吧?