ADO 的测试

2008-04-09 04:39:58来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

DO Cursor/Lock/Concurrency 的测试 来源:cww
  我个人认为ADO2.0在这方面的表现实在是不好,我看ADO更高的版本会不会比较好一点。或许,要在SQL7.0之下才会有良好的表现,而我使用的是SQL 6.5与Informix。怎堋说呢?
注:我终於用有SQL7.0可以Testing了,而且Concurrency的表现不错哦,所以了,如果
您想用ADO而且是SQL Server当後端,那就使用Sql7,不要用SQL6.5

我们先看一下Recordset中CursorType的属性

AdOpenForwardOnly 顺向资料指标?
AdOpenKeyset 索引键集 (Keyset) 资料指标?
AdOpenDynamic 动态资料指标?可看到其他使用者所做的增加,变更和删除结果
AdOpenStatic 静态资料指标

  以上这一些和RDO的定义没有什堋不同, 然而我也在该篇文章中指出,这些要和Cursor所在的位置与RDBMS都有相关。

  RDO中Cursor的位置可分为rdUseODBC(对应ADO的AdUseClient),rdUseServer(对应ADO的AdUseServer),rdUseNone(ADO中没有直接的对应)。ADO Recordset的CursorLocation = AdUseClient时,只有AdOpenStatic/AdOpenForwardOnly的CursorType会有作用,其他的二者和AdOpenStatic有相同的效果。如果是AdUseServer呢,在SQL Server中上述的四种CursorType都可以用,但是RecordSet中的Resync方法只有
在adOpenKeyset的CursorType才能用,AdOpenStatic不能使用。而RDO中经常使用的rdUseNone的CursorType在ADO中没有相对应的设定,那该如何呢?
那得设定
rs.CursorLocation = AdUseServer
rs.CursorType = AdOpenForwardOnly
rs.LockType = AdLockReadOnly
rs.CacheSize = 1
  来取代RDO的rdUseNone,而且注意的是不可使用Client端的Cursor,否则RecordSet Open的时间会久(因为Client端的Cursor在ADO中都是Static的Cursor而不管我们如何设)。

  OpenLink ODBC Driver for Informix又有点不一样,如果使用Server端的Cursor,那只能设定是AdOpenForwardOnly的CursorType,否则会有意想不到的结果,而使用Client端的Cursor呢,只有AdOpenStatic/AdOpenForwardOnly二者有效,不过特别的是AdOpenStatic
在这里呢却可以使用Resync的方法,只要说我们的Table有Unique的Key且有Select进来,便可以用,因为下rs.Resync adAffectCurrent 在Informix 中是以另一个查询当笔资料的Query来做(如Select * from TableName Where KeyFl eyvalue),就因为要Query到当笔,所以一定要有Unique的Key,否则Resync会有错。

再来讨论一下Lock
RecordSet的LockType有以下的设定:

adLockReadOnly 预设值。唯读 -- 您无法变更资料。
adLockPessimistic 悲观性锁定,通常会在编辑时立即在资料来源锁定记录。
adLockOptimistic 乐观性锁定,在您呼叫 Update 方法时才锁定。
adLockBatchOptimistic 悲观性批次更新

  悲观性批次更新我不讨论,而唯读也够明显了,这都不讨论。基本上SQL6.5用OLEDB Provider来连时,只有乐观锁定,SQL7.0後才有悲观锁定。SQL6.5想要有悲观锁定,那就用ODBC Provider的方式来做吧!RDO悲观锁定基本上在Resultset建立时,便会自动Fetch第一笔,所以在该笔所在的Page上会有一个Update Lock。而ADO又不太相同,它在Recordset pen之後并不会自动Fetch第一笔,直到我们想引用它或Move系列指令下达时才会有作用。


  上面的Lock是针对Recordset,也就是以Page/Record为对像,如果想要做Table Exclusive Lock於SQL6.5 设定SQL指令如下:

Select * from qppfa (TabLockX) Where ....

  TabLockX代表会对该Table做Exclusive Lock,不过这种Lock对程式设计没有太多用处,因为这种方式的Lock会在Fetch时做Table Lock,一旦Update资料或Transactiont结束後会令该Lock Release掉,如果没有Transaction,那情况是:Fetch时做Table Lock,Update
後Release Lock,Fetch下一笔时再产生Table Lock,而不是们想像的会一直做Lock。

  而Informix的Table Lock则好多,它可以用Lock Table table-name in Exclusive Mode的指令来做,也就是说我们用Connection物件的Execute方法来执行上述的指令便可。

  在SQL Server6.5之下

  1.不像RDO2.0 有一个rdConcurLock的设定;虽然ADO有一个adLockPessimistic的LockType,如果透过OLEDB Provider来做,似乎全不是那一回事,怎堋用,都是乐观的锁定。除非使用ODBC Privder的方式,才会有悲观锁定。

  2.RDO 中如果ProgramA 与 ProgramB 同时指到某一笔Record,而後ProgramA成功的Update该笔资料且Commit,而ProgramB这时也随即Update该笔资料,这时ProgramB会收到一个错误讯息,这时只要下

Recordset.Move 0
Recordset.Edit
设定更改的值
Recordset.Update 便可以重新来做一次

但是ADO呢,我个人认为在Update之後产生错误时,正确的使用方式应是:
(rs as ADODB.Recordset)
rs.CancelUpdate
rs.Resync adAffectCurrent
set new value for recordset
rs.Update
  但实№上会在rs.Resync adAffectCurrent这一行再产生错误,而此时Recordset的内容却有Refresh成Remote资料库的实№资料内容,好奇怪!我不知道这里是我的做法有误,还是SQL Server 7.0才能如此,至少SQL Server6.5我失败了。以至於Update的程式要变成:

cn.BeginTrans
On Error Resume Next
rs!fld1 = "v"
rs.Update
Do While cn.Errors.Count $#@62; 0
If cn.Errors(cn.Errors.Count - 1).Number = -2147217887 Then
-2147217887 代表该Record可能被他人更新了 for Server端Cirsor
ans = MsgBox("资料更新有冲突,是否再试一次", vbYesNo)
If ans = vbYes Then
rs.CancelUpdate
rs.Resync adAffectCurrent 这里也会产生一个error
cn.Errors.Clear
rs!fld1 = "v"
rs.Update
Else
Exit Do
End If
Else
Exit Do
End If
Loop

If cn.Errors.Count = 0 Then
cn.CommitTrans
Else
cn.RollbackTrans
End If

  以上程式是rs.CursorLocation = adUseServer 的情况,而用rs.CursorLocation = adUseClient呢,情况又不太相同,基本上这是不提供rs.Resync方法。这种程式能看吗?实在不好吧?所以在这里我的建议是,使用OLEDB Provider来连SQL6.5时,最好是同一笔资料同时间被Update的机率很小,如果发生了,就只好Requery,再想办法指到该笔,再重新Update,要不就要用上面的方式,再不就产生错误,要使用者再重新执行一次。只要同时Update的可能性小,可能好几年都不会遇上同时Update的问题。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:在记忆体中的ADO资料录集与DataBindin

下一篇:ADO 在informix的 Addnew