标签:object 巴西 命令 免费 more 持久 target 列表 对象引用
作者:Doug Hennig 翻译:老瓷
在VFP应用程序中,有很多方法可以访问非VFP数据(如SQL Server):
远程视图、SQL Passthrough(SPT--译者著)、ADO、XML……本文件将探讨不同机制的利弊,并讨论何时适合使用特定策略。我们还将研究VFP中一种令人兴奋的新技术CursorAdapter,它将使访问远程数据比早期版本更容易。
越来越多的VFP开发人员将数据存储在VFP表以外的其他地方,如SQL Server或Oracle。这有很多原因,包括VFP表的脆弱性(感知上和实际上)、安全性、数据库大小和公司标准。微软在每一个版本中都使非VFP数据的访问变得更加容易,甚至还鼓励它在VFP7 CD中加入MSDE(微软数据引擎,一个免费的、精简版的SQL Server)。
然而,访问后端数据库从未像使用VFP表那样容易。此外,还可使用多种机制来执行此操作:
你应该选择哪种机制?答案(正如大多数VFP问题的答案)是“取决于”。它取决于许多因素,包括开发团队的经验和专业知识、基础设施、应用程序的需求、预期的未来需求等等。
让我们来看看这些机制中的每一种,包括它们的优点和缺点,需要注意的一些技术,以及我对每一种机制在整体方案中的位置的看法。我们还将了解我认为VFP 8中最大的新特性之一CursorAdapter类,以及它如何使通过ODBC、ADO或XML进行远程数据访问变得更加容易和一致。
与本地视图一样,远程视图只是在数据库容器中定义的预定义SQL SELECT语句。不同之处在于,远程视图通过ODBC(即使它访问的数据是VFP)而不是本机访问数据。
可以使用create SQL view命令以编程方式创建远程视图,也可以使用视图设计器以可视化方式创建远程视图。在这两种情况下,都需要指定要使用的ODBC连接。连接可以是在系统上设置的ODBC数据源(DSN),也可以是已在同一数据库中定义的连接对象。下面是一个示例,它创建了SQL Server附带的示例Northwind数据库的Customers表的远程视图(我们将在示例中广泛使用该数据库)。这是从GENDBC生成的代码中摘录的;实际上还有很多代码可以设置连接、视图和字段的各种属性。
CREATE CONNECTION NORTHWINDCONNECTION ; CONNSTRING "DSN=Northwind SQL; UID=sa; PWD=testdb; " + ; "DATABASE=Northwind; TRUSTED_CONNECTION=No" CREATE SQL VIEW "CUSTOMERSVIEW" ; REMOTE CONNECT "NorthwindConnection" ; AS SELECT * FROM dbo.Customers Customers DBSetProp(‘CUSTOMERSVIEW‘, ‘View‘, ‘UpdateType‘, 1) DBSetProp(‘CUSTOMERSVIEW‘, ‘View‘, ‘WhereType‘, 3) DBSetProp(‘CUSTOMERSVIEW‘, ‘View‘, ‘FetchMemo‘, .T.) DBSetProp(‘CUSTOMERSVIEW‘, ‘View‘, ‘SendUpdates‘, .T.) DBSetProp(‘CUSTOMERSVIEW‘, ‘View‘, ‘Tables‘, ‘dbo.Customers‘) DBSetProp(‘CUSTOMERSVIEW.customerid‘, ‘Field‘, ‘KeyField‘, .T.) DBSetProp(‘CUSTOMERSVIEW.customerid‘, ‘Field‘, ‘Updatable‘, .F.) DBSetProp(‘CUSTOMERSVIEW.customerid‘, ‘Field‘, ‘UpdateName‘, ; ‘dbo.Customers.CustomerID‘) DBSetProp(‘CUSTOMERSVIEW.companyname‘, ‘Field‘, ‘Updatable‘, .T.) DBSetProp(‘CUSTOMERSVIEW.companyname‘, ‘Field‘, ‘UpdateName‘, ; ‘dbo.Customers.CompanyName‘)
可以升迁现有应用程序的最简单方法之一是使用升迁向导创建VFP表的SQL Server版本,然后创建新数据库(例如REMOTE.DBC),并在该数据库中创建与它们所基于的表同名的远程视图。这样,打开远程视图的代码将与打开本地表的代码完全相同,只是您将首先打开其他数据库。例如:
if oApp.lUseLocalData open database Local else open database Remote endif use CUSTOMERS
如果在窗体和报表的数据环境中使用游标对象,则需要做一些额外的工作,因为这些对象引用了将视图拖放到数据环境中时选择的特定数据库。要处理此问题,请将类似于以下内容的代码放入DataEnvironment的BeforeOpenTables方法中:
local loObject for each loObject in This.Objects if upper(loObject.BaseClass) = ‘CURSOR‘ and not empty(loObject.Database) loObject.Database = iif(oApp.lUseLocalData, ‘local.dbc‘, ‘remote.dbc‘) endif upper(loObject.BaseClass) = ‘CURSOR‘ .. next loObject
需要注意的一点是:当您打开一个视图时,VFP会尝试在DBC中锁定该视图的记录,即使它只是短暂的。这可能会在繁忙的应用程序中引起争用,在这些应用程序中,多个用户可能会尝试同时打开窗体。尽管有一些解决方法(将DBC复制到本地工作站并使用该方法,或者在VFP 7和更高版本中,使用SET reproces SYSTEM来增加锁争用的超时),但这是需要计划的。
关于偏僻的景色是不是一件好事,有很大的争议。如果您有兴趣阅读有关论点各方面的内容,请查看以下链接:
http://fox.wikis.com/wc.dll?Wiki~RemoteViews~VFP
http://fox.wikis.com/wc.dll?Wiki~MoreOnRemoteViews~VFP
http://fox.wikis.com/wc.dll?Wiki~Client/ServerDataAccessTechniques~VFP
http://fox.wikis.com/wc.dll?Wiki~Client/ServerTechniquesPerformance~VFP
远程视图的优点是:
远程视图的缺点是:
基本上,这归结为一个控制问题:远程视图使处理后端数据变得容易,但代价是限制了对它们的控制。
远程视图实际上只适用于客户机-服务器、直接连接到数据的两层应用程序。我相信,从长远来看,如果使用n层设计开发,大多数应用程序将更加灵活、健壮,并且具有更长的保质期,因此,远程视图最适合于这样的情况:您正在对现有应用程序进行升迁,而不想重新设计/重新开发它,或者您的开发团队对其他技术没有太多经验。
VFP提供了许多函数,有时称为SQL passthrough(或SPT)函数,这些函数允许您访问后端数据库。SQLCONNECT()和SQLSTRINGCONNECT()连接到后端数据库引擎;这两个函数的区别在于,SQLCONNECT()需要现有的ODBC数据源(DSN)在用户系统上定义,而SQLSTRINGCONNECT()只是将必要的信息直接传递给ODBC,即无DSNless连接。如您所料,SQLDISCONNECT()从后端断开连接。SQLEXEC()向数据库引擎发送一个命令(如SQL SELECT语句),通常(但不一定,取决于命令)将返回的结果放入VFP游标中。
下面是一个打开到Northwind数据库的连接的示例(假设有一个名为“Northwind”的DSN定义了如何连接到此数据库),检索单个客户记录并将其显示在浏览窗口中,然后关闭连接。
lnHandle = sqlconnect(‘Northwind‘) if lnHandle > 0 sqlexec(lnHandle, "select * from customers where customerid = ‘ALFKI‘") browse sqldisconnect(lnHandle) else aerror(laErrors) messagebox(‘Could not connect: ‘ + laErrors[2]) endif lnHandle > 0
要改用无DSN连接,请将SQLCONNECT()语句替换为以下内容(将服务器名称、用户ID和密码替换为适当的值):
lnHandle = sqlstringconnect(‘Driver=SQL Server;Server=(local);‘ + ; Database=Northwind;uid=sa;pwd=whatever‘)
DispLogin SQL设置控制ODBC是否显示登录对话框。尽管您可能认为让ODBC担心用户名和密码很方便,但您无法控制对话框的外观,也无法控制如果用户输入不正确的值会发生什么。相反,您最好在自己的VFP对话框中向用户请求适当的信息,然后将该信息传递给ODBC。如SQLCONNECT()函数的VFP帮助中所述,应该使用SQLSETPROP()将DispLogin设置为3。
与其让每个需要访问远程数据的组件管理自己的ODBC连接,不如使用一个对象,该对象的唯一职责是管理连接和访问数据。基于Custom的SFConnectionMgr就是一个例子。它有几个自定义属性,其中一些属性必须先设置,然后才能使用它连接到远程数据源。
属性 | 描述 | ||
cDatabase | 要连接到的数据库;如果填写了cDSN,则可以留空。 | ||
cDriver | 要使用的ODBC驱动程序或OLE DB提供程序;如果填写了cDSN,则可以留空。 | ||
cDSN | 要连接到的ODBC DSN;留空则使用无DSN连接。 | ||
cErrorMessage | 发生任何错误的消息。 | ||
cPassword | 数据源的密码;如果使用受信任的连接,则可以留空。 | ||
cServer | 数据库所在的服务器;如果填写了cDSN,则可以留空。 | ||
cUserName | 数据源的用户名;如果使用受信任的连接,则可以留空。 | ||
lConnected | 如果已连接到数据源则为.T. 。 |
它有几个自定义方法:
方法 | 描述 |
Connect | 连接到数据源。 |
Disconnect | 断开数据源连接(Destroy调用,也可手动调用)。 |
Execute | 对数据源执行语句。 |
GetConnection | 返回连接句柄或ADO连接对象。 |
GetConnectionString | 从各种连接属性(受保护)返回连接字符串。 |
HandleError | 当发生错误时设置cErrorMessage属性(受保护)。 |
SFConnectionMgr不打算直接使用,但它是SFConnectionMgr ODBC和SFConnectionMgr ADO的子类,分别针对ODBC和ADO。这些子类重写大多数方法以提供所需的特定行为。让我们看看SFConnectionMgrODBC。
Init方法将当前的dislogin设置保存为自定义的ndislogin属性,并将其设置为3,这样就永远不会显示登录对话框。
This.nDispLogin = sqlgetprop(0, ‘DispLogin‘) sqlsetprop(0, ‘DispLogin‘, 3) dodefault()
Connect方法检查我们是否已经连接,然后如果在cDSN属性中指定了DSN,则使用SQLCONNECT()或生成连接字符串并使用SQLSTRINGCONNECT()函数。不管怎样,如果连接成功,nHandle属性都包含连接句柄,而lConnected是.T。如果连接失败,nHandle是0,lConnected是.F,而cErrorMessage包含有关出错的信息(在HandleError方法中设置,我们不会查看)。
* 如果尚未连接,请使用无DSN连接连接到指定的DSN或数据源。 local lcConnString with This if not .lConnected if empty(.cDSN) lcConnString = .GetConnectionString() .nHandle = sqlstringconnect(lcConnString) else .nHandle = sqlconnect(.cDSN, .cUserName, .cPassword) endif empty(.cDSN) * 如果成功连接,则设置lConnected标志,否则获取错误信息。 .lConnected = .nHandle > 0 if not .lConnected .nHandle = 0 .HandleError() endif not .lConnected endif not .lConnected endwith return This.lConnected
GetConnectionString从连接属性的值返回连接字符串。
local lcSpecifier, ; lcConnString with This lcSpecifier = iif(upper(.cDriver) = ‘SQL SERVER‘, ‘database=‘, ; ‘dbq=‘) lcConnString = ‘driver=‘ + .cDriver + ‘;‘ + ; iif(empty(.cServer), ‘‘, ‘server=‘ + .cServer + ‘;‘) + ; iif(empty(.cUserName), ‘‘, ‘uid=‘ + .cUserName + ‘;‘) + ; iif(empty(.cPassword), ‘‘, ‘pwd=‘ + .cPassword + ‘;‘) + ; iif(empty(.cDatabase), ‘‘, lcSpecifier + .cDatabase + ‘;‘) + ; ‘trusted_connection=‘ + iif(empty(.cUserName), ‘yes‘, ‘no‘) endwith return lcConnString
Execute方法对数据源执行一个语句(如SQL SELECT命令)。它首先调用Connect以确保我们有一个连接,然后使用SQLEXEC()函数将语句传递给数据源。
lparameters tcStatement, ; tcCursor local lcCursor, ; llReturn with This .Connect() if .lConnected lcCursor = iif(vartype(tcCursor) = ‘C‘ and not empty(tcCursor), ; tcCursor, sys(2015)) llReturn = sqlexec(.nHandle, tcStatement, lcCursor) >= 0 if not llReturn .HandleError() endif not llReturn endif .lConnected endwith return llReturn
Disconnect方法断开与数据源的连接,并将nHandle设置为0,将lConnected设置为.F。
with This if .lConnected sqldisconnect(.nHandle) .nHandle = 0 .lConnected = .F. endif .lConnected endwith
Destroy只需断开连接并恢复保存的discogin设置。
This.Disconnect() sqlsetprop(0, ‘DispLogin‘, This.nDispLogin) dodefault()
下面是一个示例(取自TestConnMgr.prg),它显示了如何使用SFConnectionMgrODBC。它首先连接到SQL Server Northwind数据库并获取所有客户记录,然后连接到Access Northwind数据库并再次检索所有客户记录。当然,本例使用硬编码连接信息;实际应用程序可能会将此信息存储在本地表、INI文件或Windows注册表中,以使其更加灵活。
loConnMgr = newobject(‘SFConnectionMgrODBC‘, ‘SFRemote‘) with loConnMgr * 连接到SQL Server Northwind数据库并获取客户记录。 .cDriver = ‘SQL Server‘ .cServer = ‘(local)‘ .cDatabase = ‘Northwind‘ .cUserName = ‘sa‘ .cPassword = ‘‘ do case case not .Connect() messagebox(.cErrorMessage) case .Execute(‘select * from customers‘) browse use otherwise messagebox(.cErrorMessage) endcase * 现在连接到Access Northwind数据库并获取客户记录。 .Disconnect() .cDriver = ‘Microsoft Access Driver (*.mdb)‘ .cServer = ‘‘ .cDatabase = ‘d:\Program Files\Microsoft Visual Studio\VB98\Nwind.mdb‘ .cUserName = ‘‘ .cPassword = ‘‘ do case case not .Connect() messagebox(.cErrorMessage) case .Execute(‘select * from customers‘) browse use otherwise messagebox(.cErrorMessage) endcase endwith
使用SPT的优点是:
使用SPT的缺点是:
与远程视图一样,SPT最适合于与数据直接连接的客户机-服务器两层应用程序。由于将现有应用程序转换为SPT要比远程视图或游标适配器(稍后我们将看到)做得更多,SPT最适合于实用程序、简单应用程序或窄焦点情况。
OLE DB和ADO是微软通用数据访问策略的一部分,在这种策略中,任何类型的数据都可以以任何格式存储在任何地方,而不仅仅是存储在本地服务器上的关系数据库中,可以供任何需要它的应用程序使用。OLE DB提供程序类似于ODBC驱动程序:它们提供了一种标准的、一致的访问数据源的方法。各种OLE DB提供程序可用于特定的DBMS(SQL Server、Oracle、Access/Jet等),而Microsoft为ODBC数据源提供OLE DB提供程序。
下面是一个示例(ADOExample.prg),它从Northwind数据库获取所有巴西客户,并显示客户ID和公司名称。注意,连接对象处理连接(记录集的ActiveConnection属性设置为连接对象),而记录集处理数据。
local loConn as ADODB.Connection, ; loRS as ADODB.Recordset loConn = createobject(‘ADODB.Connection‘) loConn.ConnectionString = ‘provider=SQLOLEDB.1;data source=(local);‘ + ; ‘initial catalog=Northwind;uid=sa;pwd=‘ loConn.Open() loRS = createobject(‘ADODB.Recordset‘) loRS.ActiveConnection = loConn loRS.LockType = 3 && adLockOptimistic loRS.CursorLocation = 3 && adUseClient loRS.CursorType = 3 && adOpenStatic loRS.Open("select * from customers where country=‘Brazil‘") lcCustomers = ‘‘ do while not loRS.EOF lcCustomers = lcCustomers + loRS.Fields(‘customerid‘).Value + chr(9) + ; loRS.Fields(‘companyname‘).Value + chr(13) loRS.MoveNext() enddo while not loRS.EOF messagebox(lcCustomers) loRS.Close() loConn.Close()
由于其面向对象的特性和功能,ADO一直是n层开发的首选数据访问机制(尽管随着XML变得越来越流行,这种情况正在迅速改变)。与ODBC不同,您不必直接连接到数据源。
有关ADO和在VFP中使用ADO的详细信息,请参阅John Petersen的“ADO Jumpstart For Visual FoxPro Developers”白皮书,该白皮书可从VFP主页(http://msdn.microsoft.com/vfoxpro;按照“技术资源”、“技术文章”和“com和ActiveX开发”链接访问文档)。
使用ADO的优点是:
ADO的缺点是:
在其他组件之间来回传递数据时,ADO很容易使用。例如,VFP COM对象的方法可以很容易地将ADO记录集返回到Excel VBA代码,然后该代码可以处理和显示结果。
如果您正在使用n层体系结构设计应用程序,那么ADO可能是一个不错的选择,如果您已经熟悉它或者已经为它准备好了基础设施。然而,XML正迅速成为n层应用程序的首选机制,因此我希望ADO在这方面的应用越来越少。
XML(可扩展标记语言)并不是一种真正的数据访问机制;它实际上是一种传输技术。数据被打包成具有结构化格式的文本,然后运到某个地方。然而,由于XML只是文本,所以它比其他技术有很多优势(我们稍后将讨论)。
几年前,微软“发现”了XML,并从那时起在几乎所有地方都实现了它。内置在.NET框架ADO.NET中的数据访问技术以XML为基础(事实上,一个简单的观点是ADO.NET实际上只是一组包装类,通过OOP接口公开XML数据)。基于SOAP(简单对象访问协议)的Web服务使用XML作为通信和数据传输的基础。XML甚至正迅速成为n层应用程序的首选数据传输机制,长期以来,n层应用程序更青睐ADO。
VFP 7添加了几个与XML一起工作的函数:XMLTOCURSOR(),它将XML转换为游标;CURSORTOXML(),它将执行相反的操作;XMLUPDATEGRAM(),它将updategram(以特定格式表示对数据的更改的XML)从对游标的更改中生成。下面是一些VFP代码(取自XMLExample1.prg),展示了VFP如何处理XML:
* 获取ALFKI客户的信息并显示原始XML。 close databases all lcXML = GetCustomerByID(‘ALFKI‘) strtofile(lcXML, ‘ALFKI.XML‘) modify file ALFKI.XML erase ALFKI.XML *将其放入游标中,浏览并进行更改,然后查看updategram。 xmltocursor(lcXML, ‘CUSTOMERS‘) set multilocks on cursorsetprop(‘Buffering‘, 5) browse lcUpdate = xmlupdategram() strtofile(lcUpdate, ‘UPDATE.XML‘) modify file UPDATE.XML * 通过设置KeyFieldList属性,updategram将只包含key和changed字段。 cursorsetprop(‘KeyFieldList‘, ‘cust_id‘) lcUpdate = xmlupdategram() strtofile(lcUpdate, ‘UPDATE.XML‘) modify file UPDATE.XML erase UPDATE.XML close databases all * 此函数将指定的客户记录返回为XML。 function GetCustomerByID(tcCustomerID) local lcXML open database (_samples + ‘data\testdata‘) select * from customer where cust_id = tcCustomerID into cursor Temp cursortoxml(‘Temp‘, ‘lcXML‘, 1, 8, 0, ‘1‘) use in Temp use in Customer return lcXML
注意,在版本8之前,虽然VFP可以创建一个XML updategram,但它没有一个简单的方法来使用它(即,更新VFP表)。Visual FoxPro MVP Alex Feldstein为此编写了一个例程(http://fox.wikis.com/wc.dll?Wiki~XMLUpdateGramParse),但在VFP 8中,可以使用新的XMLAdapter类的实例来完成此操作(我们将在“VFP:Advanced中的数据策略”文档中查看该类)。
下面是一个示例(XMLExample2.prg),它使用SQLXML通过Web服务器从SQL Server获取客户记录(我们将在高级篇中更详细地讨论SQLXML),然后将更改发送回。
* 获取ALFKI客户的信息并显示原始XML。 close databases all lcXML = GetNWCustomerByID(‘ALFKI‘) strtofile(lcXML, ‘ALFKI.XML‘) modify file ALFKI.XML erase ALFKI.XML * 将其放入游标中,浏览并进行更改。 xmltocursor(lcXML, ‘CUSTOMERS‘) cursorsetprop(‘KeyFieldList‘, ‘customerid‘) set multilocks on cursorsetprop(‘Buffering‘, 5) browse * 获取updategram并将更改保存到SQL Server。 lcUpdate = xmlupdategram() SaveNWCustomers(lcUpdate) use * 此函数使用SQLXML将指定的客户记录获取为XML。 function GetNWCustomerByID(tcCustomerID) local loXML as MSXML2.XMLHTTP loXML = createobject(‘MSXML2.XMLHTTP‘) loXML.open(‘POST‘, ‘http://localhost/northwind/template/ ‘ + ; ‘customersbyid.xml?customerid=‘ + tcCustomerID, .F.) loXML.setRequestHeader(‘Content-type‘, ‘text/xml‘) loXML.send() return loXML.responseText * 此函数使用SQLXML将指定的客户记录获取为XML。 function SaveNWCustomers(tcDiffGram) local loDOM as MSXML2.DOMDocument, ; loXML as MSXML2.XMLHTTP loDOM = createobject(‘MSXML2.DOMDocument‘) loDOM.async = .F. loDOM.loadXML(tcDiffGram) loXML = createobject(‘MSXML2.XMLHTTP‘) loXML.open(‘POST‘, ‘http://localhost/northwind/‘, .F.) loXML.setRequestHeader(‘Content-type‘, ‘text/xml‘) loXML.send(loDOM)
使用XML有很多好处:
使用XML还有一些缺点:
XML有很多优点,包括存储配置设置、在应用程序组件之间传递少量数据、在备注字段中存储结构化数据等等,XML非常适合于n层应用程序,因为它易于传输(在组件之间或穿墙)和转换到数据集(如VFP游标)或从中转换。使用XML Updategrams(和更新的Diffgrams),可以限制传输的数据量。如果您正在启动新的n层项目,这显然是要使用的数据访问机制。
你可能注意到的一点是,我们所研究的每一种机制都与其他机制完全不同。这意味着每种机制都有一个新的学习曲线,将现有应用程序从一种机制转换为另一种机制是一项非常重要的任务。
在我看来,CursorAdapter是VFP 8中最大的新特性之一。我觉得他们这么酷的原因是:
这是最后一点的例子。假设您有一个应用程序使用带有CursorAdapter的ODBC来访问SQL Server数据,出于某种原因,您希望改为使用ADO。您只需更改CursorAdapters的DataSourceType并更改到后端数据库的连接,就完成了。应用程序中的其他组件既不知道也不关心这一点;它们仍然看到同一个游标,而不管用于访问数据的机制如何。
我们将仔细查看高级文档中的CursorAdapter。不过,在此期间,这里有一个示例(CursorAdapterExample.prg),它从Northwind数据库的Customers表中为巴西客户获取某些字段。游标是可更新的,因此如果您在游标中进行了更改,请将其关闭,然后再次运行程序,您将看到您的更改已保存到后端。
local loCursor as CursorAdapter, ; laErrors[1] loCursor = createobject(‘CursorAdapter‘) with loCursor .Alias = ‘Customers‘ .DataSourceType = ‘ODBC‘ .DataSource = sqlstringconnect(‘driver=SQL Server;‘ + ; ‘server=(local);database=Northwind;uid=sa;pwd=;trusted_connection=no‘) .SelectCmd = "select CUSTOMERID, COMPANYNAME, CONTACTNAME " + ; "from CUSTOMERS where COUNTRY = ‘Brazil‘" .KeyFieldList = ‘CUSTOMERID‘ .Tables = ‘CUSTOMERS‘ .UpdatableFieldList = ‘CUSTOMERID, COMPANYNAME, CONTACTNAME‘ .UpdateNameList = ‘CUSTOMERID CUSTOMERS.CUSTOMERID, ‘ + ; ‘COMPANYNAME CUSTOMERS.COMPANYNAME, CONTACTNAME CUSTOMERS.CONTACTNAME‘ if .CursorFill() browse else aerror(laErrors) messagebox(laErrors[2]) endif .CursorFill() endwith
CursorAdapter的优点本质上是所有其他技术的结合。
CursorAdapter没有太多缺点:
因为CursorAdapter创建VFP游标,所以您不太可能在n层应用程序的中间层使用它们。然而,在UI层中,我看到CursorAdapter替换了所有远程数据访问的其他技术,甚至在将来可能会被升级的新应用程序中替换了Cursor。
本文讨论了ODBC(无论是远程视图还是SQL Passthrough)、ADO和XML作为访问非VFP数据(如SQL Server或Oracle)的方法的优缺点。通常,您应该为特定应用程序选择哪种机制取决于许多因素。然而,在VFP 8中使用新的CursorAdapter技术可以更容易地过渡到远程数据访问,并且在需要时更容易在机制之间切换。
在“VFP的数据策略:高级篇”文档中,我们将详细讨论CursorAdapter类,查看使用ODBC、ADO和XML访问本机数据或非VFP数据的细节。我们还将研究如何创建可重用的数据类,并讨论如何在报表中使用CursorAdapter。
Doug Hennig是Stonefield Systems Group Inc.的合作伙伴。他是获奖的Stonefield数据库工具包(SDT)的作者和获奖的Stonefield查询的共同作者。他是《黑客视觉FoxPro 7.0指南》的合著者(与Tamar Granor、Ted Roche和Della Martin一起)和《视觉FoxPro 7.0的新特性》的合著者(与Tamar Granor和Kevin McNeish一起),均来自Hentzenwerke出版社,在Pinnacle Publishing的Pros Talk VisualFoxPro系列中,“VisualFoxPro数据字典”的作者。他在FoxTalk上写了每月的“可重用工具”专栏。他是《黑客指南》和《基础知识》的技术编辑,这两本书都来自亨森沃克出版社。自1997年以来,道格在每次微软FoxPro开发者大会(DevCon)以及北美各地的用户团体和开发者大会上都发表过演讲。他是微软最有价值的专业人士(MVP)和认证专业人士(MCP)。
标签:object 巴西 命令 免费 more 持久 target 列表 对象引用
原文地址:https://www.cnblogs.com/hnllhq/p/12349141.html