Borland® Delphi® 2005 Migration to .NET using VCL for .NET
by Bob Swart, Bob Swart Training & Consultancy
數據訪問
我們已經將一個VCL應用程序移植到.NET, 現在是時候來操作一個大點的項目了, 這次將會有更多的實際應用會遇到的問題. 這次代碼中包括數據訪問, 所以, 讓我們到Delphi7/Demos/Db 下看看. 在目錄的几個範例中, MastApp和IBMastApp是最大的, 有最多的unit(單元)和form(窗體).
如果你沒有安裝Delphi7, 那你也可打開BDS/3.0/Demos/DelphiWin32/Db目錄, 裹面同樣有MastApp 和 IBMastApp這兩個項目(但已經移植到新的項目格式了-包括bdsproj文件).
MastApp已經被移植到.NET了, 你能在BDS/3.0/Demos/Delphi.NET/DB/MastApp這個目錄下找到對應的版本, 而IBMastApp還沒移植到VCL for .NET, 所以, 你無法在BDS/3.0/Demos/Delphi.NET/DB or BDS/3.0/Demos/Delphi.NET/VCL/Db找到對應的版本.
所以, 作為我們一個重要的示範, 讓我們開始將IBMastApp應用程序從Win32移植到.NET下—一個看起來比較復雜的數據庫應用程序範例.
首先, 我們還是將必要的文件作個備份.
- 在BDS/3.0/Demos/Delphi.NET/VCL/Db目錄下創建一個新的子目錄, 名字為IBMastApp. 我們工作到最後, 會得到一個新的Delphi for .NET VCL DB項目的範例.
- 將BDS/3.0/Demos/DelphiWin32/VCLWin32/Db/IBMastApp目錄下的所有文件復製到BDS/3.0/Demos/Delphi.NET/VCL/Db/IBMastApp目錄下
- 將文件mastapp.bdsproj刪除, 因為這個文件包含了指定這個項目為Delphi Win32項目的信息(而現在我們是要將其移植到.NET)
現在我們已經準備好了開始在一個新的IBMastApp項目上工作, 并將其移植到.NET了.
- 運行Delphi 2005
- 在歡迎頁面(Welcome Page)上點擊Open Project按鈕, 并打開BDS/3.0/Demos/Delphi.NET/VCL/Db/IBMastApp目錄下的mastapp.dpr文件(因為我們是Win32的範例中復製過來的)
因為項目沒有包含有.bdsproj文件, Delphi 2005 IDE 需要詢問你來确定是陞級這個項目為Win32還是.NET的項目. 所以, 會彈出一個陞級對話框詢問你, 如下圖
在項目陞級對話框中選擇將mastapp陞級為.NET
我們會得到一個帶有.NET personality信息的mastapp.bdsproj文件. 現在保存文件, 新的個性信息將會保存到mastapp.bdspro文件.
- 選擇菜單File | Save All, mastapp項目所有的文件會被保存, 包括文件mastapp.bdsproj.
移植數據模塊(Data Module)
現在我們已經將這個項目關聯為Delphi for .NET, 接下來首先要檢查的是數據庫控件是不是指向正确的數據聯接. 你必須在編繹之前做這個工作.當數據聯接配置正常時, 我們就能將精力集中在代碼的移植上.
- 打開數據模塊(data module), 也就是DataMod.pas. 你可以在項目管理器(Project Manager)中直接雙擊DataMod.pas對應的節點
數據模塊設計如下面屏幕截圖所示, 采用了InterBase Express作為數據訪問的架構
設計期的VCL for .NET數據模塊
我們必須重新設置Database控件, 在數據模塊的右下角可以找到它.
Database控件編繹框
注意,這裹的D:/是文件路徑所在. 你可能要修改成C:/, 并且使用Common Files 代替路徑中的Borland才可以設置InterBase聯接到這個數據庫. 我默認是將mastsql.gdb安裝到C:/Program Files/Common Files/Borland Shared/Data/mastsql.gdb—你的設置可能有點不同
*注意在每一次你移植VCL項目到.NET時, 你可能都需要做這個動作: 第一, 确認數據模塊上的數據訪問控件能指到正确的數據庫. 并且,雖然大部分的數據庫控件都有對應的VCL for .NET的版本, 但是在.NET下不支持SQL鏈接, 所以, 你必須將這些項目移植改為使用dbExpress, dbGo for ADO, InterBaseExpress或者其它VCL for .NET的數據訪問技術.
移植源代碼
當數據模塊和指定的數據訪問控件修改成功後, 我們能開始第一次的項目編繹工作.
- 按Shift+F2來保存項目中所有的文件
- 按Ctrl+F9第一次編繹mastapp項目
你將會得到大概17條警告信息, 還有一個錯誤信息, 如下所示:
[Warning] mastapp.dpr(23): W1005 Unit 'Borland.Vcl.Forms' is specific to a platform
[Warning] MAIN.PAS(6): W1005 Unit 'Borland.Vcl.Windows' is specific to a platform
[Warning] MAIN.PAS(6): W1005 Unit 'Borland.Vcl.Messages' is specific to a platform
[Warning] MAIN.PAS(6): W1005 Unit 'Borland.Vcl.Graphics' is specific to a platform
[Warning] MAIN.PAS(6): W1005 Unit 'Borland.Vcl.Controls' is specific to a platform
[Warning] MAIN.PAS(7): W1005 Unit 'Borland.Vcl.Forms' is specific to a platform
[Warning] MAIN.PAS(7): W1005 Unit 'Borland.Vcl.Dialogs' is specific to a platform
[Warning] MAIN.PAS(7): W1005 Unit 'Borland.Vcl.Buttons' is specific to a platform
[Warning] MAIN.PAS(7): W1005 Unit 'Borland.Vcl.StdCtrls' is specific to a platform
[Warning] MAIN.PAS(7): W1005 Unit 'Borland.Vcl.Menus' is specific to a platform
[Warning] MAIN.PAS(7): W1005 Unit 'Borland.Vcl.ExtCtrls' is specific to a platform
[Warning] DataMod.pas(8): W1005 Unit 'Borland.Vcl.Windows' is specific to a platform
[Warning] DataMod.pas(8): W1005 Unit 'Borland.Vcl.Messages' is specific to a platform
[Warning] DataMod.pas(8): W1005 Unit 'Borland.Vcl.Graphics' is specific to a platform
[Warning] DataMod.pas(8): W1005 Unit 'Borland.Vcl.Controls' is specific to a platform
[Warning] DataMod.pas(8): W1005 Unit 'Borland.Vcl.Forms' is specific to a platform
[Warning] DataMod.pas(8): W1005 Unit 'Borland.Vcl.Dialogs' is specific to a platform
[Fatal Error] DataMod.pas(9): F1026 File not found: 'VarUtils.dcuil'
我們可以先忽略警告的信息—因為大部分只是提醒我們現在在使用VCL for .NET的單元只能運行于特定的平台. 為了避免老是出現這此平台警告信息, 你能夠屏蔽掉它們.
- 選擇Project | Options打開項目管理選項(Project Options). 在編繹信息類別(Compiler Messages category)中, 你可以將"Platform Unit"的警告選擇去掉(如下圖屏幕截圖如示). 如果你現在再重新編繹項目, 你就不會再得到同類的警告信息了.
項目管理選項—警告信息列表
[Fatal Error] DataMod.pas(9): F1026 File not found: 'VarUtils.dcuil'
引起這個錯誤的原因是VarUtils這個單元在于VCL for .NET中已經取消了(比較可能的是合并到Variants單元了).所以, 我們能夠將不在存在的VarUtils單元從uses 子句中移除.
- 將VarUtils從DataMod.pas 文件interface 處的uses 部分中移除
*注意如果你想你的項目還能同時在Win32下編繹, 你可能更願意將VarUtils單元放置在一對{$IFDEF WIN32} .... {$ENDIF}區塊中, 而不是簡單的將它從uses 子句中移除掉.
- 如果你決定采用IFDEF的解決方案, 可以象下面一樣修改uses clause 子句:
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
DB, IBQuery, IBCustomDataSet, IBTable, IBDatabase, IB, Variants
{$IFDEF WIN32}, VarUtils {$ENDIF};
-
- 按Shift+F2保存項目的所有文件, 然後按Shift+F9來重新編繹項目
現在的結果是出現3個提示和2個錯誤
[Error] EDCUST.PAS(54): E2010 Incompatible types: 'Variant' and 'Double'
[Fatal Error] BrCstOrd.pas(48): F2063 Could not compile used unit 'EDCUST.PAS'
這個包含引起類型不兼容代碼錯誤的討厭函數如下所示:
procedure TEdCustForm.Edit(CustNo: Double); begin MastData.Cust.Open; MastData.Cust.Locate('CustNo', CustNo, []); ShowModal; end;
這個錯誤信息是提示參數CustNo在MastData.Cust.Locate不匹配引起. 它的類型是Double, 但函數要求的是一個Variant類型. 這樣寫應該沒問題, 但是需要將Variants這個單元增加到uses子句中, 編繹器才能通過編繹.
- 增加Variants單元到Edcust.pas文件中implementation部分的uses子句中
- 按Shift+F2保存項目的所有文件, 然後按Shift+F9來重新編繹項目
現在會得到3個提示和1 個錯誤信息.
[Fatal Error] EDORDERS.PAS(10): F1026 File not found: 'DBLookup.dcuil'
這個指出DBLookup單元已經不存在VCL for .NET中了—或者需要在這個項目中引用它. 我們可以簡單將它移除了解決這個錯誤.
- 從Edorders.pas.的interface部分在uses 子句中將DBLookup單元移除.
*注意,如果你想你的項目還能和Win32兼容, 你可以將DBLookup單元放在{$IFDEF WIN32} .... {$ENDIF}區塊中, 而不是簡單的將其從uses子句刪除.
- 如果你決定采用IFDEF的解決方法, 你可以象下面一樣修改代碼:
uses
SysUtils, Windows, Messages, Classes, Graphics, Controls,
Dialogs, Forms, StdCtrls, DBGrids, DBCtrls, DB,
Buttons, Grids, {$IFDEF WIN32} DBLookup, {$ENDIF} ExtCtrls, Mask;
- P按Shift+F2保存項目的所有文件, 然後按Shift+F9來重新編繹項目.
現在會得到3個提示, 還有4個錯誤.
[Error] SrchDlg.pas(54): E2010 Incompatible types: 'Variant' and 'Double' [Error] SrchDlg.pas(64): E2010 Incompatible types: 'Variant' and 'Double' [Error] SrchDlg.pas(98): E2010 Incompatible types: 'Variant' and 'TCaption' [Fatal Error] EDORDERS.PAS(76): F2063 Could not compile used unit 'SrchDlg.pas'
前三個錯誤和我們剛才解決的錯誤非常相似, 同樣可以通過在uses子句中增加Variants單元來解決.
- 在SrchDlg.pas單元的implementation部分下的uses子句中增加Variants單元
- 按Shift+F2保存項目的所有文件, 然後按Shift+F9來重新編繹項目
現在出現3個提示, 1個警告,還有2個錯誤信息.
[Error] EDORDERS.PAS(105): E2010 Incompatible types: 'Variant' and 'Double' [Warning] EDORDERS.PAS(229): W1050 WideChar reduced to byte char in set expressions [Fatal Error] BrCstOrd.pas(48): F2063 Could not compile used unit 'EDORDERS.PAS'
現在我們已經知道錯誤的原因, 還有解決方法了. 警告信息部分, 將會在接下來得到處理—還是讓我們先集中精力處理掉所有的編繹錯誤.
- 給Edorders.pas單元的implementation部分下的uses 子句增加Variants單元.
- 按Shift+F2保存項目的所有文件, 然後按Shift+F9來重新編繹項目
現在還有3個提示, 1個警告, 和3個錯誤信息
- 給BrCstOrd.pas單元的implementation部分下的uses 子句增加Variants單元.
- 按Shift+F2保存項目的所有文件, 然後按Shift+F9來重新編繹項目
現在會得到3個提示, 1個警告, 和1個錯誤信息
- 將DBLookup從Edparts.pas 的(interface 下)uses子句中刪除, 或者將DBLookup單元放置到一個{$IFDEF WIN32}的區塊中, 如下所示:
uses
SysUtils, Windows, Messages, Classes, Graphics, Controls,
Forms, Dialogs, DB, StdCtrls, ExtCtrls, Mask, DBCtrls,
{$IFDEF WIN32} DBLookup, {$ENDIF} Buttons;
- 按Shift+F2保存項目的所有文件, 然後按Shift+F9來重新編繹項目
現在會得到3個提示, 1個警告, 和2個錯誤信息
- 給Edparts.pa單元的implementation部分下的uses 子句增加Variants單元.
- 按Shift+F2保存項目的所有文件, 然後按Shift+F9來重新編繹項目
現在會得到3個提示, 1個警告, 和2個錯誤信息
- 給Brparts.pas單元的implementation部分下的uses 子句增加Variants單元.
- 按Shift+F2保存項目的所有文件, 然後按Shift+F9來重新編繹項目
如果你運行的是已經陞級過(安裝過補丁)的Delphi 2005版本, 那麼現在你的程序已經能夠通過編繹和鏈接了, 你可以直接參考本文的"運行野生海產入口登記程序(Running the Marine Adventure Order Entry Application)"部分. 如果你發現還是遇到錯誤, 那可接著往下看.
現在會得到3個提示, 1個警告, 和1個嚴重錯誤信息
[Hint] DataMod.pas(244): H2443 Inline function 'ExpandFileName' has not been expanded
because unit 'System.IO' is not specified in USES list
[Hint] DataMod.pas(743): H2443 Inline function 'FileExists' has not been expanded because
unit 'System.IO' is not specified in USES list
[Hint] DataMod.pas(748): H2443 Inline function 'ExtractFileName' has not been expanded
because unit 'System.IO' is not specified in USES list
[Warning] EDORDERS.PAS(229): W1050 WideChar reduced to byte char in set expressions
[Fatal Error] CustRpt.pas(6): F1026 File not found: 'Quickrpt.dcuil'
在這個時候, 你還會遇到一個運行時錯誤對話框提示當Delphi 2005 VCL設計器試圖顯示CustRpt單元時無法找到對應屬性.
未完侍續