第四部分

原文

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,DAO,RDO,ADO,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程序员使用的DATA控件,同时,升级向导只是在使用了这个控件的地方标记了不再支持之类的注释。按照文档里的注释仅仅是获得了一般性的信息,并不会给升级带来多大的帮助。在VB6里,我可以创建一个AX控件工程,然后将数据控件添加进去,以及一些函数、过程也加进去是的客户端程序中的容器能够访问它。这个接口看起来就像这样:

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
会被Data1.RecordSetAddNew替代

Data1.Recordset.Fields("[Territory Num]") = RTrim(LTrim(txtTerritoryNum.Text))
会被Data1.RecordSetFields "[Territory Num], RTrim(LTrim(txtTerritoryNum.Text))替代
等等。对于String这样行之有效,其它的RecordSetFields需要其它类型的字段,或者RecordSetField声明使用变体类型作为值类型,并且通过VarType函数来检测类型是否正确。如果你仅仅是想要DATA控件被自身所控制,这样做是可以的,但是使用DATA控件的主要的重点就是绑定到诸如DBGrid这样的控件。如果真想正确地这样做的话就应该将自定义控件变成一个真正的VB数据源,这就超出本文要描述的范围了,而且一旦转换到.NET还不一定会有用。对于像尝试这种方案的人(当然了,这种方案还是有可能成功的),我建议你在NSDN帮助文档里搜索"Creating a Data Source"来获取更过的信息。
我使用了一个相似的技巧来转换一个VB6窗体到.NET。窗体设计成允许新的记录被添加到一个存在的数据库,可以想象,这由三部分组成,一个DATA控件用来访问数据库,一个DBGrid(从VB5)用来展示数据库中的记录,以及一整套文本框用来填写新纪录的各项数值。我采用了我上面创建的自定义的DATA控件并且添加了一个DBGrid(从VB5)。我还包含了一些用来调整大小的算法,使得网格始终能覆盖整个控件区域。接着,我为数据控件设定了数据源,然后组件了AX控件。在我转换的时候,我从VB程序里移除了DATA控件和DBGrid,然后用我新定义并且包含了以上两者的控件来替代。我将程序升级到VB.NET结果跑得很好。同样地,创造性地使用AX控件可以是其它不可能的转换工作变得相当地简单。
在VB数据库连接性里ADO.NET还是最大变化的其中之一。对于ADO,程序应该总是被连接到数据库的(注意ADO可以在未连接模式下使用,但是大多数VB6程序使用正常的连接模式)。在某些方面,这种简化的数据库会编程控制一个为用来实现程序中数据库的记录和表被更改时的自动更新。但是这也导致了一个扩展功能的问题,因为大多数数据库供应商在允许并发连接数上是收费的项目之一。然而ADO的连接数往往在整个VB程序的运行周期中存在着,同时其License也被捆绑着。有时候这个问题很小,但是如果程序有很多用户呢,或者更糟糕的是被链接到互联网上,那么此时花费一个额外的时间来使用License是一个很大的开销。同时大量的开放连接到数据库也会是整体性能降低。
对于ADO.NET,在程序或者用户与数据要进行交互时每一个连接变成了读、写、升级数据库、以及关闭这些操作。这虽然给程序员带来了一点小小的工作量,但是使得速度快了那么一点,并且使得程序容易扩展。
一个绕开完全重写的捷径就是切换到.NET平台,但是要继续使用ADO而不是ADO.NET,ADO作为MSADO15.DLL中实例化的一个COM对象使得这成为可能。就像所有的COM对象一样,.NET需要一个包装类来访问ADO DLL,那就是adodb.dll,同样你也可以自己创建一个来源于任何版本ADO的类,使用我上个月简述的tlbimport.exe工具就可以办到了。一如既往地,你有另一个选择,那就是如果一个窗体可以从应用程序的其它部分中分离开来,那么它将可以被转换成一个AX控件来添加到.NET的窗体中。这个技巧还有另一个优点,在于ADO有些函数在ADO.NET中是无效的,特别是服务器游标和ADO扩展(ADOX)。
我说过,从基于连接的ADO范例移植到不基于ADO.NET的范例将会给性能带来一个提升,而且可扩展性的提升更多。还有一些切换到ADO.NET的理由。ADO使用类似于表的记录集,而ADO.NET使用类似于数据库的数据集。在ADO中要访问一个以上的表,查询的时候形成了必须在表与表之间连接的记录集。在ADO.NET里,数据集包括了所有的表以及DataReleation对象(类似于真实数据库中的外键)。这使得复杂的数据操作变得容易得多。老客户端游标功能仍然可以在DataReader对象中找到。另一个大区别就是,在ADO仅能够加载数据到记录集的时候ADO.NET还能够将数据装成像数组和列表等许多"普通"的编程结构。哪里有ADO标被只向前的游标访问,哪里就同样有ADO.NET表的索引子,并且还可以像其它集合一样被访问。还有,大多数.NET控件,甚至是文本框,允许绑定的数据不只是文字,但除了像颜色等其它属性(详见:ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1033/dnadvnet/html/vbnet02122002.htm)。
最后要说的是,ADO.NET是基于XML的,这使得在对象和程序之间传递数据变得更容易更高效;使用XML而不是ADO的COM调用也意味着数据可以不用经过配置修改就可以通过防火墙。

下一步

这样就完成了我们会用到的一般代码和数据库相关代码的转换。下个月,在最后一部分我们将介绍ASP到ASP.NET的转换,以及转换到VB.NET 2005和C#;然后还会总结一下一些关于什么时候转换是有意义的想法。


 

【VB/.NET】Converting VB6 to VB.NET 【Part II】【之四】的更多相关文章

  1. VB6与VB.NET对照表

    VB6与VB.NET对照表 VB6.0 VB.NET AddItem Object名.AddItem Object名.Items.Add ListBox1.Items.Add ComboBox1.It ...

  2. 浅析vb.net与vb6的不同

    vb6.0与vb.net 都是微软公司推出的编程工具,而vb.net是在vb6的基础上发展而来的,其语法与VB6.0相似,但VB.net并不是VB6.0 的简单升级,而是增加了更多特性,其中重要的一点 ...

  3. VBA/VB6/VBS/VB.NET/C#/Python/PowerShell都能调用的API封装库

    API函数很强大,但是声明的时候比较繁琐. 我开发的封装库,包括窗口.键盘.鼠标.消息等常用功能.用户不需要添加API函数的声明,就可以用到API的功能. 在VBA.VB6的引用对话框中引用API.t ...

  4. vb6转vb.net

    一直在用vb6写软件,但最近系统要做web版,但之前的业务规则全在代码中写死了,没用使用存贮过程,如果在web端重写规则,则工作量太大,项目时间也不允许,只好把业务规则转到vb.net中.现在的vb. ...

  5. vb delphi7、2010 csharp vb.net空白测试程序

    工作中难免在网上看到一段不错的代码,希望能够拿来测试一次,为了避免每次测试都要新建一个空白测试程序,索性预先建立好,要用的时候复制一遍,然后打开直接粘贴需要测试的代码进行测试.

  6. 自写函数VB6 STUFF函数 和 VB.net 2010 STUFF函数 详解

    '*************************************************************************'**模 块 名:自写函数VB6 STUFF函数 和 ...

  7. VB6.0 和VB.NET 函数对比

    VB6.0和VB.Net的对照表 VB6.0 VB.NET AddItem Object名.AddItem Object名.Items.Add ListBox1.Items.Add ComboBox1 ...

  8. VB6.0和VB.Net的函数等对照表

    VB6.0和VB.Net的对照表 VB6.0 VB.NET AddItem Object名.AddItem Object名.Items.Add ListBox1.Items.Add ComboBox1 ...

  9. VB操作EXCEL文件

    用VB操作Excel(VB6.0)(整理) 首先创建Excel对象,使用ComObj:Dim ExcelID as Excel.ApplicationSet ExcelID as new Excel. ...

随机推荐

  1. Spring注入静态变量(转)

    今天碰到一个问题,我的一个工具类提供了几种静态方法,静态方法需要另外一个类的实例提供处理,因此就写出了这样的代码: Class Util{ private static XXX xxx; xxx = ...

  2. 添加Main-Class到manifest中

    Maven默认打包生成的jar是不能够直接运行的,因为带有main方法的类信息不会添加到manifest中(打开jar文件中的META-INF/MANIFEST.MF文件,将无法看到Main-Clas ...

  3. Sting和StringBuffer的区别

    java.lang.String代表不可变序列: s1 = "hello"; s2 = "world"; s1 = s1 + s2; 内存分配情况是s1有块内存 ...

  4. HDU 1599 find the mincost route (无向图floyd最小环详解)

    转载请注明出处:http://blog.csdn.net/a1dark 分析:终于弄懂了floyd的原理.以前的理解一直肤浅.所以一做到floyd应用的题.就拙计了.其实floyd的本质DP.利用前K ...

  5. 使用Eclipse EE开发web项目

    最近使用EclipseEE开发web项目,遇到了以下几个问题: 1. 通过tomcat启动web应用的时候,总是提示找不到包或者class. 经过排查,发现所有的jar包并没有放到WEB-INF/li ...

  6. [转]java-Three Rules for Effective Exception Handling

    主要讲java中处理异常的三个原则: 原文链接:https://today.java.net/pub/a/today/2003/12/04/exceptions.html Exceptions in ...

  7. hdu 4812 D Tree(树的点分治)

    D Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total ...

  8. SQL 2008 数据库迁移

    1,改动迁移路径 USE master GO ALTER DATABASE 数据库名  --主数据 MODIFY FILE(NAME='数据库名', FILENAME='F:\DataBase\数据库 ...

  9. Swift - 使用atlas图集实现动画效果(SpriteKit游戏开发)

    我们通常继承SKSpriteNode来实现游戏中的元素,除了可以使用图片作为纹理皮肤外.我们还可以使用动画纹理集来实现动画播放. 动画纹理集的制作也很简单,首先要有一套动画序列图,然后把它们放到一个文 ...

  10. 用asio的定时器实现带超时的connect,备忘

    // test.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <boost/asio.hpp> #inclu ...