【VB/.NET】Converting VB6 to VB.NET 【Part II】【之四】
第四部分
原文
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】【之四】的更多相关文章
- VB6与VB.NET对照表
VB6与VB.NET对照表 VB6.0 VB.NET AddItem Object名.AddItem Object名.Items.Add ListBox1.Items.Add ComboBox1.It ...
- 浅析vb.net与vb6的不同
vb6.0与vb.net 都是微软公司推出的编程工具,而vb.net是在vb6的基础上发展而来的,其语法与VB6.0相似,但VB.net并不是VB6.0 的简单升级,而是增加了更多特性,其中重要的一点 ...
- VBA/VB6/VBS/VB.NET/C#/Python/PowerShell都能调用的API封装库
API函数很强大,但是声明的时候比较繁琐. 我开发的封装库,包括窗口.键盘.鼠标.消息等常用功能.用户不需要添加API函数的声明,就可以用到API的功能. 在VBA.VB6的引用对话框中引用API.t ...
- vb6转vb.net
一直在用vb6写软件,但最近系统要做web版,但之前的业务规则全在代码中写死了,没用使用存贮过程,如果在web端重写规则,则工作量太大,项目时间也不允许,只好把业务规则转到vb.net中.现在的vb. ...
- vb delphi7、2010 csharp vb.net空白测试程序
工作中难免在网上看到一段不错的代码,希望能够拿来测试一次,为了避免每次测试都要新建一个空白测试程序,索性预先建立好,要用的时候复制一遍,然后打开直接粘贴需要测试的代码进行测试.
- 自写函数VB6 STUFF函数 和 VB.net 2010 STUFF函数 详解
'*************************************************************************'**模 块 名:自写函数VB6 STUFF函数 和 ...
- VB6.0 和VB.NET 函数对比
VB6.0和VB.Net的对照表 VB6.0 VB.NET AddItem Object名.AddItem Object名.Items.Add ListBox1.Items.Add ComboBox1 ...
- VB6.0和VB.Net的函数等对照表
VB6.0和VB.Net的对照表 VB6.0 VB.NET AddItem Object名.AddItem Object名.Items.Add ListBox1.Items.Add ComboBox1 ...
- VB操作EXCEL文件
用VB操作Excel(VB6.0)(整理) 首先创建Excel对象,使用ComObj:Dim ExcelID as Excel.ApplicationSet ExcelID as new Excel. ...
随机推荐
- 基于visual Studio2013解决C语言竞赛题之1050矩阵反斜线求和
题目 解决代码及点评 /************************************************************************/ /* 50 ...
- [置顶] Guava学习之Lists
Lists类主要提供了对List类的子类构造以及操作的静态方法.在Lists类中支持构造ArrayList.LinkedList以及newCopyOnWriteArrayList对象的方法.其中提供了 ...
- CodeForces 462B Appleman and Card Game(贪心)
题目链接:http://codeforces.com/problemset/problem/462/B Appleman has n cards. Each card has an uppercase ...
- hdu1104 Remainder bfs找算式是否有解……
须要注意的是,进行模运算剪枝-- #include<iostream> #include<queue> #include<cstdlib> #include< ...
- 七牛用户如何将视频转码成普清高清来适应不同的手机端或者web端
Qiniu 七牛问题解答 非常多人会用到七牛视频转码问题,要将视频转码成适用于各种终端的视频,也有的用户对转码服务的码率,帧率,分辨率等理解不多.不知道该怎样设置这些參数.以下我给大家科普一下. 问题 ...
- asp.net2.0安全性(1)--用户角色篇(起篇)--转载来自车老师
安全管理的解决方案在.net1.1中几乎为一片空白,对于应用程序的验证与授权大部分的工作是开发人员自己编写代码,或者是借助企业库等工具来实现,此可谓.net1.1中的一大缺憾.在.net2.0中微软为 ...
- ASP.NET - 对URL传递的值进行编码Server.UrlEncode()
/// <summary> /// 搜索内容 /// </summary> /// <param name="sender"></para ...
- 14.18.1 The InnoDB Recovery Process InnoDB 恢复进程:
14.18.1 The InnoDB Recovery Process InnoDB 恢复进程: InnoDB crash recovery 有几个步骤组成: 1.应用redo log,Redo lo ...
- 深入理解extern使用方法
一. extern做变量声明 l 声明externkeyword的全局变量和函数可以使得它们可以跨文件被訪问. 我们一般把全部的全局变量和全局函数的实现都放在一个*.cpp文件中面,然后用一个同名的 ...
- Android菜鸟的成长笔记(14)—— Android中的状态保存探究(上)
原文:[置顶] Android菜鸟的成长笔记(14)—— Android中的状态保存探究(上) 我们在用手机的时候可能会发现,即使应用被放到后台再返回到前台数据依然保留(比如说我们正在玩游戏,突然电话 ...