Star Yu的学习历程

导航

 
[作者注:已经转贴到:http://www.cnblogs.com/begincsdn/archive/2005/07/14/192501.html]  
    strSQLt = "SELECT * FROM MaxID WHERE cType='10A';"
      rsSystem.Open strSQLt, cnSystem, adOpenDynamic, adLockPessimistic
      With rsSystem
        If Not .EOF Then
          txtVouchID = !cFirstStr
          lngID = !iCurrentID + 1
          !iCurrentID = lngID
          .Update
          txtVouchID = txtVouchID & Format(lngID, "00000000")
        Else
          GoTo ErrorHandler
        End If
        .Close
      End With
上面这段代码是一个企业内部应用的代码中的一段,且不论这段代码倒底结构或功能如何,我们关注点是在rsSystem.Open上。
这段代码的功能是生成指定类型单据的单据号,因为是顺序增量产生的,所以代码中
使用lngID=!iCurrentID+1,以期达到该值加1的目的,并且不允许同时有两次同号生成。
但这段代码在实际应用中总是出现问题,即总有重复的单号产生,对于我,并不熟悉VB,但仔细阅读这段代码后。觉得这段代码
有点像操作系统临界区的味道。

仔细看:如果两个人同时进入Open阶段,如果按悲观锁定,是不是只有一个人能打开呢?

我们知道,在ADO的RecordSet打开时,有四种锁方式:
adLockReadOnly        预设值。唯读 -- 您无法变更资料。
adLockPessimistic     悲观性锁定,通常会在编辑时立即在资料来源锁定记录。
adLockOptimistic      乐观性锁定,在您呼叫 Update 方法时才锁定。
adLockBatchOptimistic 悲观性批次更新。

根据上面的提示,还不能完全确定这段代码是不是有问题。
事实上是有问题的,因为adLockPessimistic 只对Update才锁定,对于Select本身并无效,
在第一个操作者Update之前,第二个Select操作成功并获取了当前的MaxID后,结果就麻烦了。
第一个人Update成功,第二也因为取得了上一次操作者所取得的最大值而操作成功。
两张同单号单据产生了。

解决办法:
使用Update语句在前。语句改写成:
strSQLt = "Update MaxID set iCurrentID=iCurrentID+1 where cType='10A';SELECT * FROM MaxID WHERE cType='10A';"
后面不再在程序内作计算即可以解决该问题啦。



posted on 2005-03-01 17:31  Star Yu  阅读(1721)  评论(2编辑  收藏  举报