查看文章 |
多层数据库开发(六)---:什么是数据集
2008-09-03 17:32
第六章 什么是数据集 Delphi 4中有四种类型的标准数据集构件,分别是TTable、TQuery、TStoredProc和TClientDataSet。这些数据集构件都是从一个共同的基类TDataSet继承下来的,其中,只有TClientDataSet是直接从TDataSet继承下来的,而TTable、TQuery、TStoredProc的直接上级是TDBDataSet,TDBDataSet的上级是TBDEDataSet,TBDEDataSet 的上级才是TDataSet。这几个类之间的继承关系可以用图6.1来表示。 图6.1 数据集的继承关系 TDataSet是所有数据集的抽象基类,它的大部分属性和方法是虚拟的或抽象的。所谓虚拟的方法,是指这些方法可以被派生类重载。所谓抽象的方法,是指这些方法只有声明,没有定义,派生类必须给出定义后才能调用这些方法,不同的派生类可以有不同的定义。 由于TDataSet中包含抽象的方法,您不能直接创建它的实例,否则会引起运行期错误。 如果从功能上划分,TDataSet的属性和方法可以分为这么几大块:打开和关闭数据集、浏览记录、编辑数据、书签管理、控制连接、访问字段、记录缓冲区管理、过滤、事件。 6.1 打开和关闭数据集 在对数据集进行任何操作之前,首先要打开数据集。要打开数据集,可以把Active属性设为True,例如: CustTable.Active := True; 也可以调用Open函数,例如:CustQuery.Open; 要关闭数据集,可以把Active属性设为False或者调用Close函数。 6.2 数据集的状态 数据集的状态(State属性)决定了当前能够对数据集进行的操作,例如,当数据集已经关闭,它的状态是dsInactive,此时就不能访问数据集的任何数据。 6.2.1 State属性 State属性是只读的,下面列出了State属性可能的值: .dsInactive 数据集已关闭,不能访问它的数据; .dsBrowse 数据集已打开,可以浏览数据但不能修改数据; .dsEdit 此时为编辑状态,可以修改数据; .dsInsert 此时可以插入一条新的记录; .dsSetKey 只适用于TTable和TClientDataSet,此时可以设置范围和键值,并且可以调用GotoKey函数; .dsCalcFields 正在处理OnCalcFields事件,此时不能修改非计算字段的值; .dsCurValue 内部使用; .dsNewValue 内部使用; .dsOldValue 内部使用; .dsFilter 正在进行过滤操作。 当一个数据集刚刚打开的时候,它的State属性被设为dsBrowse,以后,State属性的值会随着应用程序的操作自动变化。 要使数据集进入dsBrowse、dsEdit、dsInsert或dsSetKey状态,就得调用相应的方法。 例如,要使数据集CustTable进入dsInsert状态,程序示例如下: Procedure TForm1.InsertButtonClick(Sender: TObject); Begin CustTable.Insert;{进入dsInsert状态} AddressPromptDialog.ShowModal; If AddressPromptDialog.ModalResult := mrOK then CustTable.Post; {恢复为dsBrowse状态} Else CustTable.Cancel; {恢复为dsBrowse状态} End; 从上面这个例子可以看出,有些操作会使数据集自动变成dsBrowse状态,例如,调用Post函数如果成功的话,数据集就恢复为dsBrowse状态,如果调用Post没有成功,数据集仍然保持原来的状态。调用Cancel也能使数据集恢复为dsBrowse状态。 如果把Active属性设为False,或者调用Close,将使数据集进入dsInactive状态。例如,下面两行代码是等价的: CustTable.Active := False; CustTable.Close; 有些状态如dsCalcFields、dsCurValue、dsNewValue、dsOldValue和dsFilter不能被应用程序所控制,而是由数据集本身根据需要自动设置的。例如,当正在处理OnCalcFields事件时,就自动进入dsCalcFields状态。当退出处理OnCalcFields事件的句柄时,数据集自动恢复成原先的状态。 当数据集的状态发生改变时,会触发TDataSource构件的OnStateChange事件,如果这个TDataSource构件的DataSet属性指定了这个数据集的话。 下面详细介绍数据集的各种状态以及怎样进入这些状态。 6.2.2 dsInactive状态 当数据集已关闭时,就处于dsInactive状态。此时,不能访问它的任何数据。 要使数据集进入dsInactive状态,可以把Active属性设为False,或者调用Close。在数据集将要关闭之前,会触发BeforeClose事件。当数据集刚刚关闭,会触发AfterClose事件。如果在数据集处于dsEdit或dsInsert状态时调用Close,应当在处理BeforeClose事件的句柄中提示用户是认可还是取消。程序示例如下: Procedure CustTable.VerifyBeforeClose(DataSet: TDataSet) Begin If (CustTable.State = dsEdit) or (CustTable.State = dsInsert) then Begin If MessageDlg('认可修改吗?', mtConfirmation, mbYesNo, 0) = mrYes then CustTable.Post; ElseCustTable.Cancel; End; End; 6.2.3 dsBrowse状态 当一个数据集刚刚打开的时候,数据集总是处于dsBrowse状态,此时,可以显示数据集中的记录,但不能编辑和插入记录。 dsBrowse状态可以认为是数据集的基本状态,在此状态下,可以进入其他状态。例如,调用Insert或Append函数将使数据集的状态从dsBrowse变成dsInsert(当然,这还取决于其他因素,如CanModify属性的值),调用SetKey将使数据集从dsBrowse变成dsSetKey状态。 TDataSet有两个方法可以使数据集回到dsBrowse状态,一个是Cancel,它将取消当前正在进行的编辑、插入、搜索等操作,使数据集回到dsBrowse状态。另一个是Post,它将试图把修改了的数据保存到数据集中,如果成功的话,数据集将回到dsBrowse状态,如果没有成功,数据集仍然保持原先的状态。 6.2.4 dsEdit状态 如果应用程序要修改数据集的数据,必须首先进入dsEdit状态。要进入dsEdit状态,可以调用Edit。不过,调用Edit并不能保证一定能进入dsEdit状态,这还取决于CanModify属性的值。如果这个属性返回True的话,表示数据集是可以读和写的。 对于TTable构件来说,如果ReadOnly属性设为True,CanModify属性肯定返回False。对于TQuery构件来说,如果RequestLive属性设为False,CanModify属性肯定返回False。 即使数据集进入了dsEdit状态,也并不意味着用户就一定能修改数据,数据控件的ReadOnly属性还必须设为False。此外,对于SQL数据库来说,用户能不能修改数据还取决于用户有没有修改数据的权限。 要从dsEdit状态返回到dsBrowse状态,可以调用Cancel、Post或Delete函数,其中,如果Post和Delete没有调用成功的话,就仍然保持dsEdit状态。 在数据控件中,当用户修改了数据后把输入焦点移走,就相当于调用Post函数,将使数据集回到dsBrowse状态。 6.2.5 dsInsert状态 如果应用程序要插入新的记录,必须首先进入dsInsert状态。要进入dsInsert状态,可以调用Insert或Append函数。不过,调用Insert或Append并不能保证一定能进入dsInsert状态,这还取决于CanModify属性的值是否返回True。 即使数据集进入了dsInsert状态,也并不意味着用户就一定能插入记录,数据控件的ReadOnly属性还必须设为False。此外,对于SQL数据库来说,用户能不能插入记录还取决于用户有没有修改数据的权限。 要从dsInsert状态返回到dsBrowse状态,可以调用Cancel、Post或Delete函数,其中,如果Post没有调用成功的话,就仍然保持dsInsert状态。 在数据控件中,当用户修改了数据后把输入焦点移走,就相当于调用Post,将使数据集回到dsBrowse状态。 6.2.6 dsSetKey状态 可以调用Locate、Lookup在数据集中搜索特定的记录。对于TTable构件来说,还可以调用GotoKey、GotoNearest、FindKey或FindNearest在表格中搜索特定的记录。在调用上述方法之前,必须首先使数据集进入dsSetKey状态。要使数据集进入dsSetKey状态,可以调用SetKey。调用了上述方法后,数据集又回到dsBrowse状态。 另外,可以对数据集进行过滤。对于TTable构件来说,还可以预先设置范围。在进行过滤和范围操作前,也要首先进入dsSetKey状态。 6.2.7 dsCalcFields状态 当OnCalcFields事件被触发时,就会使数据集进入dsCalcFields状态。在处理OnCalcFields事件的句柄中,应当给出“计算字段”的值。 在dsCalcFields状态下,除了“计算字段”外,应用程序不能修改其他字段的值,因为如果其他字段的值发生变化,又会导致OnCalcFields事件被触发,从而导致无限循环。 当OnCalcFields事件处理完毕,数据集又回到dsBrowse状态。 6.2.8 dsFilter状态 当OnFilterRecord事件被触发时,就会使数据集进入dsFilter状态。在此状态下,不允许修改数据集的记录,否则,过滤就无法正确执行。 当OnFilterRecord事件处理完毕,数据集就回到dsBrowse状态。 6.2.9 dsNewValue、dsOldValue或dsCurValue 在允许缓存更新的情况下,当用户修改数据集的记录时,数据集有可能会进入dsNewValue、dsOldValue或dsCurValue状态。在这三种状态下,可以通过字段(TField)的NewValue、OldValue或CurValue属性来访问当时的值。 上述三个状态是由Delphi 4内部使用的,应用程序无法主动进入上述三种状态。 6.3 浏 览 记 录 每个活动的数据集都有一个指针,指向当前记录。很多对数据集的操作都是针对当前记录,许多数据控件也只显示当前记录的数据,因此,在数据库应用程序中知道当前记录的位置是非常重要的。 数据库应用程序往往要改变当前记录的位置,这时候就要用到下面这些方法: .First 使第一条记录成为当前记录; .Last 使最后一条记录成为当前记录; .Next 使下一条记录成为当前记录; .Prior 使前一条记录成为当前记录; .MoveBy 使距离当前 |
最近读者: