第四部分
原文
DLLs,DAO,RDO,ADO,and AD.NET; the History of VB DBs
In the early versions of VB,there were no database controls,and databases were accessed by vendor-specific DLLs,but VB's power and ease of creating forms still made it a favorite among database programmers. One thing that made it so easy to create forms in VB was VBXs,the forerunners of ActiveX controls. In VB3,Microsoft added DAO (Data Access Objects),allowing easy access to ODBC databases,and a good thing was started. RDO (Remote Data Objects) came next. Where DAO focused on connecting to small Access-type databases,RDO targeted a different market,large databases such as MS sql and Oracle,so to a large extent RDO complemented rather than replaced DAO. ADO was to be the technology to combine the two.Upgrading from the earlier DAO or RDO architectures will be difficult. The Data control that was typically used by DAO and RDO programmers is not supported by .NET,and the upgrade wizard just marks each place the data control is used with a comment that it is no longer supported. Following the comment to the documentation just leads to generic information about upgrading with no further help.
I have had some success creating an ActiveX control in VB6,adding the data control to the new ActiveX control,then adding functions and subroutines to make the data control accessible to its container in the VB client program. The accessors looked like
Public Sub SetDataBaseName(Name As String) Data.DatabaseName = Name End Sub Public Sub SetRecordSource(Source As String) Data.RecordSource = Source End Sub Public Sub Refresh() Data.Refresh End Sub Public Sub RecordSetAddNew() Data.Recordset.AddNew End Sub Public Sub RecordSetFields(Field As String,Name As String) Data.Recordset.Fields(Field) = Name End Sub
In the client VB program,
Data1.RecordSet.AddNew
was replaced with
Data1.RecordSetAddNew,
Data1.Recordset.Fields("[Territory Num]") = RTrim(LTrim(txtTerritoryNum.Text))
which was replaced with
Data1.RecordSetFields "[Territory Num],RTrim(LTrim(txtTerritoryNum.Text)),
and so on. This worked well for strings,other RecordSetFields needed for other types of fields,or RecordSetField declared using Variant as the value type,and detecting the proper type by using the VarType function. This works all right if you just want to use the Data control by itself,but the whole point of using the Data control is to bind it to controls such as the DBGrid. To make that work correctly would require making the custom control a true VB data source. This is beyond the scope of this article,and might not work once converted to .NET. For anyone wishing to try this (and it might work),search for "Creating a Data Source" in the MSDN help files for more information.
I used a similar trick to convert a VB6 form to .NET. The form was designed to allow adding new records to an existing database. It could be considered as having three parts,a Data control for accessing the database,a DBGrid (from VB5) for displaying the records in the database,and a set of TextBoxes for inputting the values for the new record. I took the custom data control I created above and added a DBGrid (from VB5) to it. I included some resizing logic so that the grid always covered the entire control area. Next,I set the data source for grid to the data control and built the ActiveX control. I removed both the Data control and the DBGrid from the VB program I was converting,and replaced them with my new custom control containing both. It upgraded to VB.NET and ran fine. Again,being creative in using custom ActiveX controls can make otherwise impossible conversions fairly simple.
ADO.NET is one of the biggest changes yet in VB database connectivity. In ADO,programs were meant to always be connected to the database (note that ADO could be used in a disconnected mode,but most VB6 programs used the normal connected mode). In some ways,this simplified database programming a bit because changes made to records and tables in the program were automatically updated in the database. It also causes a scalability issue because one of the things most database vendors charge for is the number of allowed simultaneous connections. Since ADO connections tend to exist for the entire time the VB program is running,a license is tied up as well. Sometimes this does not matter,but if the program has a lot of users,or even worse,is accessed over the Internet,tying up a license for an extended time like this can get very expensive. Having a large number of open connections to the database can slow overall performance as well.
With ADO.NET,connections are opened to read,write,or update the database,and closed while the program or user works with the data. This causes a little more work for the programmer,but generates a slightly faster,and much more scalable program.
One half-step way to get around a complete rewrite is to switch to .NET,but continue to use ADO instead of ADO.NET. This can be done because ADO is implemented as a COM object in msado15.dll. Like all COM objects .NET needs a wrapper to access the ADO DLL. The .NET framework includes a wrapper for this DLL called adodb.dll,but you can also create your own from any version of ADO by using the tlbimport.exe utility that was briefly mentioned last month. Another option is,as always,that if a form can be separated from the rest of the application,it can be converted into an ActiveX control and added to a .NET form. Another advantage to using one of these techniques is that ADO has a few functions that are not available in ADO.NET,most notably server-side cursors and ADO extensions (ADOX).
I have already mentioned that moving from the connected ADO paradigm to the disconnected ADO.NET paradigm will give a boost in performance,and a big boost in scalability. There are other reasons to switch to ADO.NET,too. ADO uses recordsets that resemble tables; ADO.NET uses datasets that resemble databases. To access more than one table in ADO,the query forming the recordset had to do a join across the tables; in ADO.NET,the dataset can contain all the tables,as well as DataReleation objects,which resemble foreign keys in a real database. This can make complex data manipulations much easier. The old client-side Cursor functionality can still be found in the DataReader object. Another big difference is that while ADO can only load data into record sets,ADO.NET can also load data into many "normal" programming structures such as arrays and lists. Where ADO tables were accessed by forward only cursors,ADO.NET tables have indexers,and can be accessed like any other collection. Also,most of the .NET controls,even text Boxes,allow data binding not to just text,but to other properties such as color(Note From the Author: This URL will only work if Visual Studio is installed on your computer)(see ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1033/dnadvnet/html/vbnet02122002.htm).
Finally,ADO.NET is based on XML,which makes moving data between objects and programs easier and more efficient; using XML for this instead of ADO's COM calls also means that data can pass through firewalls without configuration changes.
Next Up
That completes our coverage of converting general and database code. Next month,in the final installment,we will cover ASP to ASP.NET conversion,and converting to VB.NET 2005 and C#; and conclude with some thoughts on when it makes sense to convert.
译文:
DLLs,AD.NET:VB DBs 的历史
在早期的VB里,是没有数据库控件的,而且要通过供应商提供的DLL文件来访问数据库。但是VB的性能以及创建窗体的简便使它仍然受数据库程序员的欢迎。VB中的VBX(Visual Basic Extension)使得创建窗体是如此的容易,它就是ActiveX控件的前身。在VB3里,微软加入了DAO(Data Access Object)使得访问ODBC数据库更加的方便,一个好东西就这么诞生了。接着RDO(Remote Data Objects)出现了。DAO主要是链接到小型接入式数据库,而RDO则针对另一个不同的市场,像MS sql 和Oracle这样大型的数据库。因此RDO只是很大程度上弥补了DAO的空缺,而不仅是替代了它。ADO则是组合了两者的新技术。
从早期的DAO或者RDO架构升级是一件困难的事情。.NET不支持DAO和RDO程序员通常使用的数据库控件,同时,升级向导只是在使用了这个控件的地方标记了不再支持云云的注释。按照文档里的注释仅仅是获得了几乎没有价值的信息,并不会给升级带来多大的帮助。
在VB6里,我已经成功地创建一个AX控件,同时还加入了这些个数据控件添,以及一些函数、过程也加进去使得VB客户端程序中的容器能够访问它。这个访问器看起来就像这样:
Public Sub SetDataBaseName(Name As String) Data.DatabaseName = Name End Sub
Public Sub SetRecordSource(Source As String) Data.RecordSource = Source End Sub Public Sub Refresh() Data.Refresh End Sub Public Sub RecordSetAddNew() Data.Recordset.AddNew End Sub Public Sub RecordSetFields(Field As String,Name As String) Data.Recordset.Fields(Field) = Name End Sub
在VB的客户端程序里:
Data1.RecordSet.AddNew
原文链接:https://www.f2er.com/vb/258760.html会被Data1.RecordSetAddNew替代
Data1.Recordset.Fields("[Territory Num]") = RTrim(LTrim(txtTerritoryNum.Text))
将写成Data1.RecordSetFields "[Territory Num],RTrim(LTrim(txtTerritoryNum.Text))
等等。这对于字符串行之有效,其它的RecordSetFields需要其它类型的字段,或者RecordSetField声明使用变体类型作为值类型,并且通过VarType函数来检测真正的类型。如果你仅仅是想让数据库控件被自身所使用,这样做是没有问题的,但是使用数据库控件的真正意义是在于绑定到诸如DBGrid这样的控件。如果真想正确地使用控件的话就应该将自定义控件变成一个真正的VB数据源,这就超出本文的讨论范围了,而且一旦转换到.NET还不一定会能用。对于像尝试这种方案的人(当然了,这种方案还是有可能成功的),我建议你在NSDN帮助文档里搜索"Creating a Data Source"来获取更过的信息。
我使用了一个类似的技巧来转换一个VB6窗体到.NET。窗体设计成允许增加新的记录到一个存在的数据库,可以想象,这由三部分组成,一个数据库控件用来访问数据库,一个DBGrid控件(从VB5)用来展示数据库中的记录,以及一整套TextBox用来填写新纪录的各项数值。我采用了我上面创建的自定义的数据库控件并且添加了一个DBGrid(从VB5)。我还包含了一些用来调整大小的算法,这样子网格始终能覆盖整个控件区域。接着,我为数据控件的网格设定了数据源,然后组件了AX控件。在我转换的时候,我从VB程序里移除了数据控件和DBGrid,然后用我新定义并且包含了以上两者的控件来替代。我将程序升级到VB.NET结果跑得很好。同样地,创造性地使用AX控件可以使其它不可能的转换工作变得相当地简单。
在VB数据库耦合性里ADO.NET还是最大变化的其中之一。对于ADO,程序应该总是被用来连接到数据库的(注意ADO也可以在离线模式下使用,但是大多数VB6程序使用在线模式)。在某些方面,这种简化的数据库会编程控制一个位用来实现程序中数据库的记录和表被更改时的自动更新。但这也导致了一个扩展功能的问题,因为大多数数据库供应商在诸多项目中的允许并发连接数上是收费的。然而ADO的连接数问题往往在整个VB程序的运行周期中存在着,同时也与一份证书关联着。有时候这个问题很小,但是如果程序有很多用户呢,或者更糟糕的是被链接到互联网上,那么此时花费一个额外的时间占用License是一个很大的开销。同时大量的数据库开放连接数也会使整体性能降低。
在ADO.NET上,连接用于开放给读、写或者升级数据库,当程序或者用户与数据要进行交互时连接就会关闭。这虽然给程序员带来了一点小小的工作量,但是使得速度快了那么一点,并且使程序扩展性更强。
一个避免全部重写的捷径就是切换到.NET平台,但是要继续使用ADO而不是ADO.NET。这其实可以实现,因为ADO的实现是作为MSADO15.DLL中的COM对象。就像所有的COM对象一样,.NET需要一个包装类(基于COM Interop)来访问ADO DLL,那就是adodb.dll,同样你也可以自己创建一个来源于任何版本ADO的dll,使用我上个月简述的tlbimport.exe工具就可以办到了。同样地,你也有另一个选择,那就是如果一个窗体可以从应用程序的其它部分中独立出来,那么它将可以被转换成一个AX控件来添加到.NET的窗体中。这个技巧还有另一个优点,在于ADO有些函数在ADO.NET中是无效的,特别是服务器游标(Server-Side Cursors)和ADO扩展(ADOX)。
我说过,从连接式ADO范例移植到非连接式ADO.NET的范例将会给性能带来一个提升,而且可扩展性的提升更多。还有一些切换到ADO.NET的理由。ADO使用类似于表的记录集,而ADO.NET使用类似于数据库的数据集。在ADO中要访问一个以上的表,在查询形成记录集时必须在表与表之间产生结点。在ADO.NET里,数据集包括了所有的表以及DataReleation对象(类似于真实数据库中的外键)。这使得复杂的数据操作变得容易得多。老客户端游标功能特色仍然可以在DataReader对象中找到。另一个大区别就是,在ADO仅能够加载数据到记录集的时候ADO.NET还能够将数据加载成许多"normal"编程中的数据结构,比如array和list。哪里有ADO表被前向游标访问,哪里就同样有ADO.NET表的索引器,并且还可以像其它集合一样被访问。还有,大多数.NET控件,甚至是文本框,允许绑定的数据不只是文字,还有诸如颜色等的属性(详见:ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1033/dnadvnet/html/vbnet02122002.htm)。
最后要说的是,ADO.NET是基于XML的,这使得在对象和程序之间传递数据变得更容易更高效;使用XML而不是ADO的COM调用也意味着数据可以不用经过配置修改就可以通过防火墙。
Next Up
这样就完成了我们会用到的一般代码和数据库相关代码的转换。下个月,在最后一部分我们将介绍ASP到ASP.NET的转换,以及转换到VB.NET 2005和C#;然后还会总结一下一些关于什么时候转换是有意义的个人看法。
Update Log:
2014-4-9 22:12