ADO 对象的游标类型(CursorTypeEnum)游标位置(CursorLocation)锁定方法(LockTypeEnum)的超详解析以及使用方法

1、首先什么是游标?

      这里引用微软官方的ADO API中的一段话来解释(机器翻译太烂,添加个人翻译)

      关系数据库中的操作会对整个行集起作用。 由 SELECT 语句返回的行集包括满足该语句的 WHERE 子句中条件的所有行。 这种由语句返回的完整行集称为结果集。 (对于)应用程序,特别是那些处于交互式并处于联机状态(的应用),并不能总是有效地把整个结果集作为一个单元来使用。 这些应用程序需要一种每次处理一行或一部分行的机制。 游标就是对结果集的一种扩展,(它为应用程序)提供了这种机制。

      游标是通过游标库来实现的。游标库是软件,通常作为数据库系统的一部分或数据访问 API来实现,用于管理从数据源 (结果集) 返回的数据的属性。 这些属性包括并发管理、 在结果集中的位置、返回的行数,以及是否可以通过结果集(可滚动性)向前或向后(或两者)移动。

      游标会跟踪结果集中的位置,并允许你对结果集逐行执行多个操作,无论是否返回原始表的行。换句话说,游标从概念上讲是返回了基于数据库中表的结果集。 光标这样命名是因为它指示着结果集中的当前位置,就像计算机屏幕上的光标指示当前位置一样。

      若要继续了解在 ADO 中其用法的详细信息,熟悉游标的概念很重要。使用游标,你可以:

  • 指定定位在结果集中的特定行。

  • 基于当前的结果集位置的行检索一行或一个行块。

  • 修改结果集中当前位置行中的数据。

  • 向其他用户所做的数据更改定义不同级别的敏感度。

    例如,假设一个应用程序潜在购买者会显示可用产品的列表。 买方滚动列表以查看产品详细信息和成本,并最终选择一个产品进行购买。 对列表的其余部分会出现其他滚动和所选内容。 就关心的是购买者,产品会出现一次,但应用程序使用可滚动游标向上和向下浏览结果集。

      记录集的open()方法的原型是这样的:

      HRESULT Recordset15::Open ( const _variant_t & Source, const _variant_t & ActiveConnection,enum CursorTypeEnum CursorType, enum LockTypeEnum LockType, long Options )

2、游标类型

CursorTypeEnum
{
    adOpenUnspecified = -1,
    adOpenForwardOnly = 0,  
    adOpenKeyset = 1,       
    adOpenDynamic = 2,      
    adOpenStatic = 3        
};

(1)静态记录集:当前用户打开记录集后,记录集就保持不变一直到关闭后再次打开它。在这过程中如果数据库中的相应记录发生改变,在当前用户是看不到的。

    adOpenForwardOpnly——光标只能向前移动,它仅支持从一开始的行提取到结果集的末尾

    adOpenStatic——打开一个静态类型的游标。静态游标始终显示结果集,与光标第一次打开时一样。根据实现,静态游标可以是只读或读/写的,并提供向前和向后滚动。静态游标永远不会检测其他更新、 删除和插入。如果你的应用程序并不需要检测数据改变,而且需要滚动,静态游标是最佳选择。

(2)动态记录集:记录集会实时的反映出数据库中相应记录的更改

    adOpenDynamic—— 打开一个完全动态的游标。动态游标可检测对结果集中的行进行的所有更改,而不管这些更改是从光标内部还是由光标外的其他用户发生。所有的 insert、 update 和 delete 语句所做的更改,所有用户都可通过游标可见。动态游标可以检测游标打开后对结果集中的行,顺序和值所做的任何更改。

    adOpenKeyset——保持当前记录集的个数不变,它只体现更新操作,不体现删除和添加操作,即只能看到其他用户对记录集数据的更新操作。

 

3、游标锁定方法

什么是锁定?

      锁定是DBMS限制对多用户环境中的行进行访问的过程。 当某行或列以独占的方式锁定时,其他用户将不被允许访问锁定的数据,直到锁定被释放。 这确保了两个用户不能同时更新连续的同一列。

      从资源角度来看,锁可能非常昂贵,只有在需要保存数据完整性时才应使用锁。 在数以百计或数千用户可能每秒都试图访问记录的数据库中(如连接到Internet的数据库),不必要的锁定可能会导致应用程序的性能下降。

 

LockTypeEnum
{
    adLockUnspecified = -1,
    adLockReadOnly = 1,
    adLockPessimistic = 2,
    adLockOptimistic = 3,
    adLockBatchOptimistic = 4
};

(1)adLockReadOnly——缺省值,只读锁定记录。

      Recordset对象以只读方式启动,无法更改数据。 只读锁是锁定类型中执行效率最快的,因为它不需要服务器来维持这个记录锁。

(2)adLockPrssimistic——悲观锁定记录。

      提供程序通过在编辑之前立即在数据源上锁定记录来确保成功的编辑记录。 当然,这意味着一旦开始编辑,其他用户就无法使用记录,直到您通过调用Update方法来释放锁定。 在不能同时更改数据的系统中使用此类型锁,例如在机票预订系统中。

(3)adLockOptimistic——乐观锁定记录。

      这意味着另一个用户可能会在你编辑记录和调用Update方法的期间更改数据,这会造成数据冲突。 在发生冲突的可能性较低或可以轻松解决冲突的情况下使用此锁定类型。

(4)adLockBatchOptimistic——开放式批量更新锁:批量更新模式需要。

      许多应用程序一次获取多个行,然后需要进行协调更新,包括要插入,更新或删除的整个行集。 使用批量光标,只需要与服务器通信一次,从而提高了更新性能并降低了网络流量。 使用批量游标库可以创建一个静态游标,然后断开与数据源的连接。 此时,你可以对行进行更改,然后重新连接并将更改发布到批处理中的数据源。

 

4、游标位置属性

 

        指示光标服务的位置(Recordset对象和Connection对象均可设置)      

         属性详解:    

     This property setting affects connections established only after the property has been set. Changing the CursorLocation property has no effect on existing connections.

       此属性设置仅影响属性设置后建立的连接。 更改CursorLocation属性对现有连接没有影响。(意即该属性必须在连接建立之前设置)

      Cursors returned by the Execute method inherit this setting. Recordset objects will automatically inherit this setting from their associated connections.

        由Execute方法返回的游标继承此设置。 Recordset对象将自动从它们的关联连接来继承这个设置。

 

        This property is read/write on a Connection or a closed Recordset, and read-only on an open Recordset.

        此属性在一个连接或关闭的记录集上是可读取/写入的,在打开的Recordset上为只读。

 

CursorLocationEnum
{
    adUseNone = 1,
    adUseServer = 2,
    adUseClient = 3,
    adUseClientBatch = 3
};

(1)adUseNone——不使用游标服务(这个常量已经过时,并且仅出于向后兼容性的考虑)

(2)adUseServer——服务器游标,默认值。使用数据提供者的或驱动程序提供的游标。这些游标有时非常灵活,对于其他用户对数据源所作的更改具有额外的敏感性。但是,Microsoft Client Cursor Provider(如已断开关联的记录集)的某些功能无法由服务器端游标模拟,通过该设置将无法使用这些功能。

(3)adUseClient——客户端游标。使用由本地游标库提供的客户端游标。 本地游标服务通常允许使用的许多功能可能是驱动程序提供的游标无法使用的,因此使用该设置对于那些将要启用的功能是有好处的。为了向后兼容,还支持同义adUseClientBatch

 

 

 

5、最常见的问题:获取记录集的RecordCount属性总为-1

分析:

       如果将 CursorLocation 属性设置为 adUseClient,则只支持 adOpenStatic 的设置。如果设置了不支持的值,不会导致错误,并将使用最接近支持的 CursorType。

      此外当要实现远程数据服务时,在与服务端通信的客户端上使用Recordset 或 Connection对象时, CursorLocation属性只能设置为adUseClient,也就是说CursorType属性的值只能设置为adOpenStatic

        PS:当游标类型CursorType设置为adOpenKeyset时,RecordCount方法也能返回实际的记录数。

解决:       

m_pRecordset->CursorLocation = adUseClient;

m_pRecordset->Open(_bstr_t(strSQL),m_pConnection.GetInterfacePtr(),adOpenStatic,adLockReadOnly,adOptionUnspecified);adUseClient;

m_pRecordset->Open(_bstr_t(strSQL),m_pConnection.GetInterfacePtr(),adOpenStatic,adLockReadOnly,adOptionUnspecified);

 

 

6、游标类型或锁定类型的特点

 

游标类型优点缺点
adOpenForwardOnly低资源要求不能向后滚动;无数据并发
adOpenStatic可滚动的    无数据并发
adOpenKeyset

部分数据并发;可滚动的

较高的资源要求;在断开连接的脚本中不可用

adOpenDynamic高数据并发;可滚动资源需求最高;在断开连接的脚本中不可用
锁定类型优点缺点
adLockReadOnly低资源要求;可扩展性高数据不能通过光标更新
adLockBatchOptimistic批处理更新;支持允许断开连接的方案;其他用户可访问数据数据可以由多个用户同时改变(可能会造成冲突)
adLockPessimistic锁定的时候其他用户不能更改数据锁定的时候会阻止其他用户访问数据
adLockOptimistic其他用户能够访问数据数据可以有多个用户同时改变(可能会造成冲突)

 

7、代码示例

 

void ADOCnn::AdoCursorsTest(CursorTypeEnum CursorType, LockTypeEnum LockType, CursorLocationEnum CursorLocation)
{
	AfxOleInit();
	HRESULT hr;
	_ConnectionPtr m_pConnection = NULL;
	m_pConnection.CreateInstance("ADODB.Connection"); //创建Connection对象实例
	m_pConnection->ConnectionTimeout = 30;  //设置连接超时时间 30s
        if (m_pConnection == NULL)
	{
		TRACE("Connection 对象创建失败! 请确认是否初始化了COM环境\r\n");
	}
	//连接字符串
	hr = m_pConnection->Open(_bstr_t(_T("Provider=OraOLEDB.Oracle.1;Password=test;Persist Security Info=True;User ID=test;Data Source=ORCL")),_bstr_t(_T("test")), _bstr_t(_T("test")), adConnectUnspecified);  
	if (SUCCEEDED(hr))// 测试数据库是否连接成功
	{
	    TRACE("数据库初始化连接成功!");
	}
       _RecordsetPtr m_pRecordset = NULL;
        m_pRecordset.CreateInstance("ADODB.Recordset");//创建记录集的对象实例
        m_pRecordset->CursorLocation = CursorLocation;//设置游标位置
        CString strSQL;
        strSQL = "select * from test"; 
        m_pRecordset->Open(_bstr_t(strSQL), m_pConnection.GetInterfacePtr(), CursorType, LockType, adOptionUnspecified);
}

需要打开什么样的记录集,只需要调用该函数并设置参数即可。

      EG . AdoCursorsTest(adOpenStatic,adLockReadOnly,adUseClient);

 

 

 

 


 

 

参考资料:

 

https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/ado-api-reference?view=sql-server-2017

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值