如何通过 TableUpdate 函数与 CursorAdapter 对象可视化 FoxPro 中更新数据

文章编号: 814184 - 查看本文应用于的产品
展开全部 | 关闭全部

本页

概要

本文介绍以下主题:
  • 如何 TableUpdate 函数与更新后端数据 CursorAdapter 类对象进行交互。
  • 如何使用,则新 CursorAdapterTableUpdate 函数以更新在 Microsoft Visual FoxPro 8.0 和可视 FoxPro 9.0 中的数据处理更新冲突。

更多信息

您可以从本地或远程数据源检索数据,通过使用可视 FoxPro 8.0 和 9.0 CursorAdapter 类。默认状态下,与 CursorAdapter 类创建的游标不会更新后端数据。若要更新后端数据,则必须设置 CursorAdapter 类的以下属性:
  • InsertCmd
  • UpdateCmd
  • DeleteCmd
如果没有设置这些属性,您可以通过设置以下 CursorAdapter 属性自动生成后端 SQL 更新命令:
  • KeyFieldList
  • UpdatableFieldList
  • UpdateNameList
  • SendUpdates

处理更新冲突

当试图使用 CursorAdapter 更新后端数据 TableUpdate 函数将返回 CursorAdapter 游标的更新的结果。如果将发生更新冲突的后端数据更新可能不会成功。但是,TableUpdate 仍可能会返回 True,因为 CursorAdapter 游标中的,数据将更新。

更新冲突是一种情况下,用户试图修改已更改,因为它已检索的记录。 下面是示例可以发生更新冲突:
  1. 用户 1 打开客户表的游标。
  2. 用户 2 更新记录号为 1,并提交该事务。
  3. 用户 1 更新记录号为 1 (通过使用 TableUpdate() 函数)。

    此位置用户 1 已更新冲突: 后会在检索更改 User1 试图更新该后端记录。

用于本机 DataSourceType 示例代码

下面的代码示例使用可视 FoxPro 8.0 本机 DataSourceType 并更新 SQL Server 罗斯文示例数据库中的记录。 要验证是否更新行,下列附加到更新命令:
CRLF+[EXECSCRIPT("IF _tally=0" + CHR(10) +
		  "ERROR('Update conflict')" + CHR(10) + "ENDIF")]
Tableupdate() 在这种情况下返回 false (F.) 并使您可以处理失败。
#DEFINE CRLF CHR(13)+CHR(10)
Local loCursor,ovfp
CLEAR
 
ON ERROR
 
Set Exclusive Off
Close Databases All
Set Multilocks On
loCursor = Createobject('CA')
* Load loCursor with the data specified in SelectCmd and display error message if error occurs.
loCursor.CursorFill()
GO top
* Display the value of the company name before update.
? "Before:",companyname
?
ovfp=Createobject("visualfoxpro.application.8")
ovfp.DoCmd("set exclusive off")
ovfp.DoCmd("update (_samples+'\northwind\customers') set companyname='Alfreds Futterkisted' where customerid='ALFKI'")
GO top
* Update the data in the cursor.
replace companyname WITH 'Alfreds Futterkiste'
* Update the back end.
retval=TABLEUPDATE(0,.F.,locursor.alias)
Messagebox("Tableupdate="+Transform(retval))
 
* If update conflict occurs, display the error.
if(retval=.F.)
 LOCAL ARRAY errors(1)
 AERROR(errors)
* Displays the errors.

 IF "Update conflict"$errors[2]
  MESSAGEBOX("Update Conflict-reverting changes")
  =TABLEREVERT(.T.,locursor.alias)
 ENDIF
endif
 * Refresh the Cursor to get the updated data.
loCursor.CursorRefresh()  && Get the data again to be sure
GO top
* Display the value of the company name after update.
?
? "After:",companyname
 
Define Class CA As CursorAdapter
 Alias = 'test1'
 DataSourceType = 'NATIVE'
 SelectCmd = 'select * from (_samples+"\northwind\customers")'
 Tables = 'Customers'
 KeyFieldList = "customerid"
 UpdatableFieldList = "companyname"
 UpdateNameList = "customerid customers.customerid,companyname customers.companyname"
 WhereType= 3
	* This is a custom property, that is added to handle update conflicts. It does not do
 * anything by itself. It is added below to the automatically-generated UpdateInsertCmd to
 * test whether anything was actually updated.
 ConflictCheckCmd =CRLF+[EXECSCRIPT("IF _tally=0" + CHR(10) + "ERROR('Update conflict')" + CHR(10) + "ENDIF")]
 
 Procedure AfterUpdate
  Lparameters cFldState, lForce, nUpdateType, UpdateInsertCmd, DeleteCmd, lResult
  * To see why it will fail on the back end, look at the UpdateInsertCmd that is used
  ? "Update Command sent="+UpdateInsertCmd
	* Swap the actual values in the command to see what occurred.
  UpdateInsertCmd=Strtran(UpdateInsertCmd,[OLDVAL('customerid','test1')],Oldval('customerid','test1'))
  UpdateInsertCmd=Strtran(UpdateInsertCmd,[OLDVAL('companyname','test1')],Oldval('companyname','test1'))
  UpdateInsertCmd=Strtran(UpdateInsertCmd,[test1.companyname],test1.companyname)
  ? "With the OLDVAL() and test1.companyname evaluated the update statement is :"+UpdateInsertCmd
  * Check tally.
  ? "Tally="+Transform(_Tally)
 
 Procedure BeforeUpdate
  Lparameters cFldState, lForce, nUpdateType, cUpdateInsertCmd, cDeleteCmd
  cUpdateInsertCmd=cUpdateInsertCmd+this.ConflictCheckCmd
 
ENDDEFINE

用于 SQL Server DataSourceType 示例代码

下面的代码示例使用 SQL Server DataSourceType 并更新 SQL Server 罗斯文示例数据库中的记录。 要验证是否在行更新,向更新命令中添加以下:
IF @@ROWCOUNT=0 RAISERROR (' Update
		  conflict.', 16, 1)
Tableupdate() 在这种情况下返回 false (F.) 并使您可以处理失败。 冲突。
LOCAL loCursor,ovfp,nhnd,lsuccess

CLEAR
SET EXCLUSIVE OFF
CLOSE DATABASES ALL
SET MULTILOCKS ON

loCursor = CREATEOBJECT('CA')

* Load loCursor with the data specified in SelectCmd and display error message if error occurs.
IF !loCursor.CursorFill()
	=AERROR(lar)
	MESSAGEBOX(lar[2]) 
ENDIF 


* Display the value of the company name before update.
? "Company Name Before Update:",companyname
?
* Create a connection handle for SQL Server so you can set up the update conflict.
nhnd=SQLSTRINGCONNECT([Driver=SQL Server; SERVER=<SQL SERVER NAME>; DATABASE=NORTHWIND])
=SQLEXEC(nhnd,[update customers set companyname='Alfreds Futterkiste' where customerid='ALFKI'])
=SQLDISCONNECT(nhnd)

* Now make a change to the local data, and then try to update it.
GO TOP
REPLACE companyname WITH 'Alfreds Futterkisted'

lsuccess=TABLEUPDATE(0,.F.,locursor.alias)
Messagebox("Tableupdate="+Transform(lsuccess))
* Error handling function. Displaying the error message if update conflict occurs.
IF !lsuccess
	=AERROR(lar)
	IF "Update conflict"$lar[2]
		MESSAGEBOX("Update conflict!-Reverting changes")
		=TABLEREVERT(.f.,locursor.alias)
	ENDIF
ENDIF  

* Get the current data from the CursorAdapter.
loCursor.CursorRefresh()  
GO TOP

* Displaying the value of the company name after update.
?
?"Company Name After Update:", companyname

DEFINE CLASS CA AS CursorAdapter
	Alias = 'test1'
	SelectCmd = 'select * from customers'
	Tables = 'Customers'
	KeyFieldList = "Customerid"
	UpdatableFieldList = "companyname"
	UpdateNameList = "customerid customers.customerid,companyname customers.companyname"
	WhereType= 3 && Key and modified 
	
	* This is a custom property that is added to handle update conflicts. It does not do
   	* anything by itself. It is added below to the automatically-generated UpdateInsertCmd to
   	* test whether anything was actually updated.
	ConflictCheckCmd =";IF @@ROWCOUNT=0 RAISERROR (' Update conflict.', 16, 1)"
	
	
	* Initializing the connectivity to Data source (SQL Server) by using ODBC driver.
	PROCEDURE init 
		WITH THIS
			.DataSourceType = 'ODBC'
			.DataSource=SQLSTRINGCONNECT([Driver=SQL Server; SERVER=<SQL SERVER NAME>; DATABASE=NORTHWIND])
		ENDWITH
	ENDPROC
	
	PROCEDURE BeforeUpdate
		LPARAMETERS cFldState, lForce, nUpdateType, cUpdateInsertCmd, cDeleteCmd
		
		? "Entering BeforeUpdate()"
		
		cUpdateInsertCmd=cUpdateInsertCmd + THIS.ConflictCheckCmd
	ENDPROC
	
	
	PROCEDURE AfterUpdate

		LPARAMETERS cFldState, lForce, nUpdateType, UpdateInsertCmd, DeleteCmd, lResult

		* To see why it will fail on the back-end, look at the UpdateInsertCmd that is used.
		? "Update Command sent="+UpdateInsertCmd

		* Swap the actual values in the command to see what occurred.
		lcActualCmd =Strtran(UpdateInsertCmd,[OLDVAL('customerid','test1')],Oldval('customerid','test1'))
		lcActualCmd =Strtran(UpdateInsertCmd,[OLDVAL('companyname','test1')],Oldval('companyname','test1'))
		lcActualCmd =Strtran(UpdateInsertCmd,[test1.companyname],test1.companyname)

		? "With the OLDVAL() and test1.companyname evaluated the update statement is :"+UpdateInsertCmd
		?
		? "Leaving AfterUpdate()"
	ENDPROC
	
	* Destroying the connection.
	PROCEDURE destroy 
		=SQLDISCONNECT(THIS.DataSource)
	ENDDEFINE

注意在上面的代码的这种方法不起作用时,使用批处理更新。 例如对于您可以使用 cursoradapter.batchupdatcount > 1. 使用批更新时, 不会触发以下事件:
  • BeforeInsert
  • afterInsert
  • 更新前
  • afterUpdate
  • BeforeDelete
  • afterDelete

参考

有关详细的信息请参阅下列主题 Visual FoxPro 帮助文件中。
  • "CursorAdapter 对象属性、 方法和事件"
  • "使用 CursorAdapters 数据访问管理"
  • "检测和解决冲突"
  • 锁定的数据
  • "管理更新的视图的"
  • "编程为共享的访问的"

属性

文章编号: 814184 - 最后修改: 2005年3月19日 - 修订: 3.4
这篇文章中的信息适用于:
  • Microsoft Visual FoxPro 8.0 专业版
  • Microsoft Visual FoxPro 9.0 Professional Edition
关键字:?
kbmt kbcodesnippet kbinfo KB814184 KbMtzh
机器翻译
注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。
点击这里察看该文章的英文版: 814184
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈