如果你有一个应用程序必须不停止的工作或表太大以致于应用程序不能在为它建立索引是停止下来,你将面临这样的问题:如果工作站或服务器崩溃,索引被破坏并要求重建时,应该怎么办?
有一个好的理由让你的表单和报表是基于视图的而不是基于表的。你可以让一个视图离线,并在用户继续查询或数据输入时重建索引。一但索引完成,从离线视图把数据更新到源表。仅需要短暂的中断来让视图离线后更新源表并重新让视图联线。事实上,如果你需要进行常规的重建索引,你可以考虑使用离线视图,并周期性的短时联线时间进行重建索引工作。
一个小的复杂的地方是,如何关闭各工作站上的视图足够长的时间来使视图离线(以及连线) 而不需要打电话告诉各个用户告诉他们关闭数据输入表单一会?我使用的方法是一种“旗语”方案:各数据输入表单监视一个需要维护的信号。当接收到该信号时,表单关闭,然后应用程序等待第二个视图状态已改变的信号(离线或联线),然后数据输入可以继续下去。在收到第二个信息前,用户不能访问数据输入表单或任何使用视图的报表。
监视信号的基础是计时器对象。在该方案中居然使用了三个有关的计时器:
当你解压本文所附的源代码(在)时,会在REINDEX 目录中生成一些文件。以下是这些文件中的一部分:
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 |
if not SYSINFO.CHNGSTATE This.Enabled = .F. do form CUSTOMER endif not SYSINFO.CHNGSTATE |
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 的表将被建立。
你可能会想当视图离线时是否可以更新源表的结构。
回答是:可能VFP 会非常不快(因此,你也会非常不快)。如果表的结构修改了,任何基于该表的视图都会受到影响。
例如,如果 LV_CUSTOMER 是用 SELECT * 命令建立的基于CUSTOMER 的视图,在该表中添加或删除一个字段;你会得到一条错误"基表字段已改变与视图不再匹配" 且视图不能打开。(有趣的是,如果在修改时视图是离线的,你可以继续以该视图工作并在online 模式下打开它并更新到源表。然而,一但你将该视图回联并试着打开它时,你将看到该错误信息)。
如果视图的每一个字段是用精确的字段名(例如SELECT CUST_ID,COMPANY,CONTACT …),字段可以添加到表中并不影响视图(如果你想通过视图向新字段输入数据,视图当然必须重新定义)。从表中删除一个字段或更名一个字段会致使“SQL 列<字段名> 未找到” 错误且视图不能打开(如果它是一个联线视图)。
如果视图是离线的,它可以被打开,但tableupdate() 将失败。
这个故事的教训是:根据你的视图是如何定义的和对表的结构进行了什么样的修改,你可能可以在对一个表的离线视图进行数据输入的同时修改该表的结构。为确保存安全,你应该在表结构改变后重新定义视图。
数据备份是另一个当源表与离线视图未关联时的维护任务。