深入CursorAdapter(三)
来源:优易学  2011-12-9 18:16:49   【优易学:中国教育考试门户网】   资料下载   IT书店

  VFP 的程序员们想要一个可重用的数据类已经很久了。尽管在过去的版本中也有许多解决这个问题的办法,不过总是有点美中不足。现在在 VFP 8里,我们有了真正的可重用数据类。这个月,Doug 为我们演示了怎样通过建立 CursorAdapter 和 DataEnvironment 的子类来建立可重用的数据类、以及怎样在表单和报表中使用它们。

  正文
  ××

  在过去的两期杂志中,我们讨论了在 VFP 8 中新增的 CursorAdapter 基础类。我个人的观点是,这是 VFP 8 中最重要的改动之一,因为它向我们提供了一个对象SQL Server这样的非VFP数据源的简单易用、统一的接口。此外,如你本月所能见到的那样,它们还形成了可重用数据类的基础。

  在讲述可重用数据类之前,让我们先来看一下我建立的一些 CursorAdapter 和 DataEnvironment 的子类,我给它们增加了一些额外的功能,它们将成为我们的可重用数据类的起点。

  SFCursorAdapter

  SFCursorAdapter (在附件 SFDataClasses.vcx 中) 是 CursorAdapter 的一个子类,它拥有一些额外增加的功能,如下:

  ※ 它可以自动处理参数化查询:你可以静态(一个常量)也可以动态(一个表达式,例如“=Thisform.txtName.value”,当 Cursor 被打开或者刷新的时候,这个表达式会被运算)的定义一个参数值。

  ※ 它可以在 Cursor 被打开以后自动在该 Cursor 上建立索引。

  ※ 对于 ADO,它还会执行一些特殊的工作,例如把 DataSource 属性设置为一个 ADO RecordSet,把这个 RecordSet 的 ActiveConnection 属性设置为一个 ADO Connection 对象,当用到一个参数化查询的时候,它还会建立一个 ADO Command 对象并把这个对象传递给 CursorFill 方法。

  ※ 它提供了简单的错误处理(cErrorMessage 属性里会有错误的信息)。

  ※ 它还有 CursorAdapter 中缺少的 Update 和 Release 方法。

  这个类的 INIT 方法建立两个集合(使用新的 Collection 基础类,它是维护某些东西的集合用的),一个是为 SelectCmd 属性可能会用到的参数而准备的,另一个是用于在 Cursor 被打开以后应该自动建立的标记。它还会 SET MULTILOCK ON,因为这是 CursorAdapter Cursor 的需求。

  This.oParameters = CreateObject('Collection')
  This.oTags = CreateObject('Collection')
  Set multilocks on

  AddParameter 方法象 parameters 集合添加一个参数。给这个方法传递参数的名称(这个名称应该与该参数出现在 SelectCmd 属性中的那个名称相一致),根据需要也可以付上参数的值(如果你现在不给它传递参数的值,也可以以后再调用 Getparameter 方法来传递)。这段代码演示了一对 VFP 8 中的新功能:新的 empty 基础类,它没有任何属性、事件或者方法,因此是建立一个轻量级的对象的理想选择;还有 AddProperty() 函数,它的作用跟 AddProperty 方法类似,区别是它用于那些没有这个方法的对象。

  lparameters tcName, tuvalue
  local loParameter
  loParameter = createobject('Empty')
  addproperty(loParmeter, 'Name', tcName)
  addproperty(loParmeter, 'value', tuvalue)
  This.oParameters.Add(loParameter, tcName)

  使用 GetParmeter 方法来返回一个特殊的 parameter 对象——通常是用在需要设置用于参数的值的时候。

  lparameters tcName
  local loParameter
  loParameter = This.oParameters.Item(tcName)
  return loParameter

  SetConnection 方法用于将 DataSource 属性设置为希望的连接。如果 DataSourceType 是 “ODBC”,就给这个方法传递一个连接句柄;如果是“ADO”,DataSource 必须是一个ADO Recordset 对象,而且该对象的 ActiveConnection 属性必须要设置为一个活动 ADO Connection 对象,所以,我们需要向 SetConnection 方法传递这个 ADO Connection 对象, SetConnection 会建立一个 RecordSet,并且把这个 RecordSet 的 ActiveConnection 设置为被传递的 ADO Connection 对象。

  lparameters tuConnection
  with this
  do case
  case .DataSourceType = 'ODBC'
  .DataSource = tuConnection
  case .DataSourceType = 'ADO'
  .DataSource = Createobject('ADODB.RecordSet')
  .DataSource.ActiveConnection = tuConnection
  endcase
  endwith

  为了建立 Cursor,我们调用 GetData 方法而不是 CursorFill 方法,因为 GetData 能够自动处理参数和错误。如果你想要建立一个不带数据的 Cursor,那么就给 GetData 方法传递一个 .T.。这个方法建立的第一样东西,是与定义在 parameters 集合中的参数们同名的私有变量(在这里调用了 GetParametervalue 方法,该方法会返回参数对象的值,如果该对象的值是一个以“=”开头的表达式,那么返回的将是运算该表达式之后所获得的值。)下一步,如果我们是在使用 ADO 并且已经有了一些参数,这段代码会建立一个 ADO Command 对象,并把该对象的 ActiveConnection 属性设置为 Connection 对象,然后把这个 Connection 对象传递给 CursorFill 方法——这是 CursorAdapter 处理 ADO 参数化查询的需要。如果我们不是在用 ADO 、或者没有任何参数,那么代码会简单的调用 CursorFill 来填充 Cursor。注意,如果给 GetData 方法传递了 .T.,并且 CursorSchema 已经被填写好了,那么就是告诉 GetData 方法去使用 CursorSchema(这也是我想让 CursorAdapter 基类拥有的功能)。现在如果 Cursor 被建立起来了,代码会调用 GreateTags 方法来为该 Cursor 建立想要的索引;如果 Cursor 没有被建好,那么它会调用 HandleError 方法来处理任何发生了的错误。

  lparameters tlNoData
  local loParameter, ;
  lcName, ;
  luvalue, ;
  llUseSchema, ;
  loCommand, ;
  llReturn
  with This

  * tlNoData参数指定是否要向 Cursor 中填充数据,如果要填充的话,
  * 我们就要把建立存储所有参数的变量的活在这里就做掉而不是放到一个其它的方法中去。
  * 因为我们希望这些变量的有效范围是私有的。

  if not tlNoData
  for each loParameter in .oParameters
  lcName = loParameter.Name
  luvalue = .GetParametervalue(loParameter)
  store luvalue to (lcName)
  next loParameter
  endif not tlNoData

  * 如果我们正在使用 ADO,并且有了一些参数,那么就需要有一个处理这些参数的 Command对象

  llUseSchema = not empty(.CursorSchema)
  if '?' $ .SelectCmd and (.DataSourceType = 'ADO' or (.UseDEDataSource and ;
  .Parent.DataSourceType = 'ADO'))
  loCommand = createobject('ADODB.Command')
  loCommand.ActiveConnection = iif(.UseDEDataSource, ;
  .Parent.DataSource.ActiveConnection, .DataSource.ActiveConnection)
  llReturn = .CursorFill(llUseSchema, tlNoData, .nOptions, loCommand)
  else

  * 填充这个 cursor.

  llReturn = .CursorFill(llUseSchema, tlNoData, .nOptions)
  endif '?' $ .SelectCmd ...

  * 如果 Cursor 建立成功,则为之定义所有的 Tag,否则则处理发生的错误。

  if llReturn
  .CreateTags()
  else
  .HandleError()
  endif llReturn
  endwith
  return llReturn

[1] [2] 下一页

责任编辑:小草

文章搜索:
 相关文章
热点资讯
资讯快报
热门课程培训