foxpro 维护源表

发表于:2007-07-02来源:作者:点击数: 标签:
如果你有一个应用程序必须不停止的工作或表太大以致于应用程序不能在为它建立索引是停止下来,你将面临这样的问题:如果工作站或 服务器 崩溃,索引被破坏并要求重建时,应该怎么办? 有一个好的理由让你的表单和报表是基于视图的而不是基于表的。你可以让一

如果你有一个应用程序必须不停止的工作或表太大以致于应用程序不能在为它建立索引是停止下来,你将面临这样的问题:如果工作站或服务器崩溃,索引被破坏并要求重建时,应该怎么办?

有一个好的理由让你的表单和报表是基于视图的而不是基于表的。你可以让一个视图离线,并在用户继续查询或数据输入时重建索引。一但索引完成,从离线视图把数据更新到源表。仅需要短暂的中断来让视图离线后更新源表并重新让视图联线。事实上,如果你需要进行常规的重建索引,你可以考虑使用离线视图,并周期性的短时联线时间进行重建索引工作。

一个小的复杂的地方是,如何关闭各工作站上的视图足够长的时间来使视图离线(以及连线) 而不需要打电话告诉各个用户告诉他们关闭数据输入表单一会?我使用的方法是一种“旗语”方案:各数据输入表单监视一个需要维护的信号。当接收到该信号时,表单关闭,然后应用程序等待第二个视图状态已改变的信号(离线或联线),然后数据输入可以继续下去。在收到第二个信息前,用户不能访问数据输入表单或任何使用视图的报表。

监视信号的基础是计时器对象。在该方案中居然使用了三个有关的计时器:

  • 重索引表单中的计时器用于执行重建索引时的等待,直到所有用户关闭了视图。然后让视图离线或联线(这要看是否重建索引是开始了或已经完成) 并传送信号到应用程序级的计时器。
  • 在数据输入表单中的计时器等待一个信号时,视图必须改变状态。当接收到该信号时,表单关闭且一个应用程序级的计时器开始工作。
  • 应用程序级的计时器,它仅在等待视图的修改状态时被启用,监视来自重索引表单中的视图状态改变信号,这样数据输入和查询可以继续。

当你解压本文所附的源代码(在)时,会在REINDEX 目录中生成一些文件。以下是这些文件中的一部分:

  • SYSINFO.DBF 是一个包含一个逻辑字段CHNGSTATE 的表(ChangeState的缩写)。该字段在通常情况下的值为.F.,当它的值被设置为.T.时,它反映了视图中所有的该状态的块必须修改。该表在应用程序运行过程中始终是打开的。
  • 应用程序菜单中的所有功能都需要一个Skip For SYSINFO.CHNGSTATE 。因此当视图的该状态被修改时,用户不能访问该功能。
  • 任何使用视图的数据输入表单都有一个计时器对象,在其Timer() 事件中的代码关闭表单并启用一个应用程序级的计时器,如果 SYSINFO.CHNGSTATE 变为.T。以下是CUSTOMER 表单中的计时器对象中的代码 (在该代码中,oTimer 是应用程序级的计时器):
if SYSINFO.CHNGSTATE messagebox(@#Closing form to perform maintenance。@# + ; @#The form will automatically reopen in just a @# + ; @#moment.@#,48) oTimer.Enabled = .T. Thisform.Release() endif SYSINFO.CHNGSTATE
  • 在应用程序启动时,一个计时器对象被实例化但是被废止的(disabled)。该计时器 仅在表单因视图处于修改状态而被强制关闭时启用,在它的Timer() 事件event 代码中搜索SYSINFO.CHNGSTATE 是否为.F.因此它可以重新打开任何因视图处于修改状态而被强制关闭的表单。以下是其代码在(在类库MYAPP.VCX 中的MyApp计时器类)中:
if not SYSINFO.CHNGSTATE This.Enabled = .F. do form CUSTOMER endif not SYSINFO.CHNGSTATE
  • 当然,这些代码是硬编码来打开CUSTOMER 表单,因为它是本例中指定的表单。在一个真正的应用程序中,你可以用一个管理对象在关闭表单将它注册到应用程序的INI文件中,管理器对象负责再次启动各个表单的备份。
  • 一个用于重建索引的表单,当用户开始重索引时或已完成时设置SYSINFO.CHNGSTATE 为 .T. 并启动计时器。正象我们已看到的那样,设置SYSINFO.CHNGSTATE 通知所有工作站上的所有打开的表单,它需要启动应用程序范围的计时器然后关闭它自己。重索引表单计时器使用试着以独占方式打开视图的方法来定期检查所有用户已经关闭视图。一但可以以独占方式打开视图,视图离线或联线 (首先更新源表),并且 SYSINFO.CHNGSTATE 设置回.F.(通知应用程序级计时器数据输入可以继续)。以下是REINDEX 表单的计时器对象的Timer() 事件的代码:
with Thisform * Disable 计时器(因此当我们执行这此代码时它不会激活) * 并看我们是否可以以独占方式打开该视图。 This.Enabled = .F. .CloseTables() select 0 use LV_CUSTOMER exclusive do case * 我们可以打开该视图,因此再关闭它,我们自己disable它 * 并转换视图的状态. case used(@#LV_CUSTOMER@#) .CloseTables() .SwitchState() * 如果我们还再尝试中,看我们是否超过了最大时间数。 * 如果是,取消处理. case seconds() - .nStartTime > .nMaxTime .cmdOffline.Click() * 再次Enable 计时器. otherwise This.Enabled = .T. endcase endwith

如果 VFP 没有安装在这些文件所在驱动器上的VFP5 目录中,修改 SETUP.PRG 并按需要修改lcDataDir 中的目录定义。运行SETUP.PRG 来在DATA目录中建立VFP 样板数据库文件TESTDATA。一个新的叫做LV_CUSTOMER的视图和一个叫SYSINFO.DBF 的表将被建立。

  1. 在运行了SETUP后,运行 MYAPP.PRG。显示一个customer 表单的实例 (注意表单标题指明视图是online的) 然后从菜单中选择重索引表。
  2. 重建索引表表单显示一个亮红色并指明重索引不能处理因为视图是online (重建索引按钮也将被废止)。
  3. 单击离线按钮。注意颜色变为黄色并指明正在等待视图离线。同时,联线按导的提示改变为取消; 这允许你在等待时取消处理。5秒钟后(客户表单中的计时器时钟),将会显示一个对话框指明客户表单将被关闭。
  4. 然后客户表单关闭,重索引表单的颜色变为绿色并指明可以进行重建索引处理。同时,取消按钮的提示变为联线,允许你将视图回联,且重建索引按钮变为可用状态。
  5. 客户表单也立即自动打开,但请注意标题指明视图是offline。单击重建索引按钮来重索引customer 表。在客户表单中修改一条记录来证明可以进行数据输入。
  6. 现在单击联线按钮并注意它自己的重复处理:客户表单关闭,重索引表表单指明视图已回联,然后客户表单在视图联线时重新打开。注意你对离线视图中的数据的修改现在 reflected 在联线视图中了。

你可能会想当视图离线时是否可以更新源表的结构。

回答是:可能VFP 会非常不快(因此,你也会非常不快)。如果表的结构修改了,任何基于该表的视图都会受到影响。

例如,如果 LV_CUSTOMER 是用 SELECT * 命令建立的基于CUSTOMER 的视图,在该表中添加或删除一个字段;你会得到一条错误"基表字段已改变与视图不再匹配" 且视图不能打开。(有趣的是,如果在修改时视图是离线的,你可以继续以该视图工作并在online 模式下打开它并更新到源表。然而,一但你将该视图回联并试着打开它时,你将看到该错误信息)。

如果视图的每一个字段是用精确的字段名(例如SELECT CUST_ID,COMPANY,CONTACT …),字段可以添加到表中并不影响视图(如果你想通过视图向新字段输入数据,视图当然必须重新定义)。从表中删除一个字段或更名一个字段会致使“SQL 列<字段名> 未找到” 错误且视图不能打开(如果它是一个联线视图)。

如果视图是离线的,它可以被打开,但tableupdate() 将失败。

这个故事的教训是:根据你的视图是如何定义的和对表的结构进行了什么样的修改,你可能可以在对一个表的离线视图进行数据输入的同时修改该表的结构。为确保存安全,你应该在表结构改变后重新定义视图。

数据备份是另一个当源表与离线视图未关联时的维护任务。

原文转自:http://www.ltesting.net