dbExpress の移行に関するその他のヒント(FireDAC)
DbExpress アプリケーションの FireDAC への移行 への移動
目次
全般
互換性のないプロパティおよびメソッド
下記のプロパティは、相当するものが FireDAC にないため、移行スクリプト FireDAC_Migrate_DBX.txt により自動的に削除されます。
- TSQLConnection:
- AutoClone - FireDAC では、すべてのデータベースについて、接続ごとに複数のアクティブな文を使用できます。
- LocaleCode - 適用されません。
- UniqueID - 適用されません。
- GetDriverFunc - FireDAC では別のドライバ アーキテクチャを使用しています。
- LibraryName - FireDAC では別のドライバ アーキテクチャを使用しています。
- ValidatePeerCertificate - サポートされていません。
- TCustomSQLDataSet:
- MaxBlobSize - FireDAC では BLOB 値を常に全部取得します。
下記のプロパティとメソッドは、直接相当するものが FireDAC になく、アプリケーションが動作しなくなるおそれがあるので、手動で削除または置換しなければなりません。
- IConnectionAdmin:
- GetDelegateDriverNames - FireDAC では "デリゲート" ドライバの概念をサポートしていません。
- RegisterDriver/UnregisterDriver - FireDAC ドライバは、アプリケーションへのリンク時に自動的に登録されます。
- TSQLConnection:
- GetCommandTypes - FireDAC コマンドの種類は TFDPhysCommandKind で列挙されています。
- GetServerMethodNames - FireDAC DataSnap 接続を使用する場合は、mkProcs メタ情報のクエリを使用してサーバー メソッドのリストを取得します。
- SetTraceEvent/TraceCallbackEvent - FireDAC には別の追跡/監視 API があります。
- MaxStmtsPerConn - FireDAC では、接続ごとに使用できる文の数に制限はありません。
- VendorLib - TFDPhysXxxDriverLink.VendorLib プロパティまたは FDDrivers.ini を使用します。
- LoadParamsOnConnect/ParamsLoaded/LoadParamsFromIniFile - FireDAC には別の接続定義 API があります。
- TCustomSQLDataSet:
- GetCommandNames - FireDAC コマンドの名前は TFDPhysCommandKind および TFDPhysMetaInfoKind で列挙されています。
- SetSchemaInfo、SchemaName、GetMetadata - 代わりに TFDMetaInfoQuery を使用します。
- ParseSelectSql、ParseDeleteSql、ParseUpdateSql、ParseInsertSql - FireDAC ではこの API をサポートしていません。代わりに、UpdateOptions.UpdateTableName、TField.ProviderFlags などを使用できます。
- TSQLMonitor - FireDAC には別の追跡/監視 API があります。
FireDAC では、dbExpress の互換性のない多くのプロパティとメソッドをエミュレートします。エミュレーションを有効にするため、移行スクリプト FireDAC_Migrate_DBX.txt では、FireDAC アプリケーションの uses 句に FireDAC.DBX.Migrate ユニットを追加します。
- メモ: 完全に制御できるようにするには、エミュレートされたメソッドを FireDAC のネイティブ メソッドに置き換えることを検討します。
例外処理
TDBXError は dbExpress 固有の例外クラスです。FireDAC には、それに相当するクラス EFDDBEngineException があります。
dbExpress 例外を処理する際には、Message プロパティまたは ErrorCode プロパティを使用して、エラーの種類を取得します。FireDAC には Kind プロパティがあり、それは列挙値を返します。詳細は、「エラーの処理(FireDAC)」を参照してください。
たとえば、次の dbExpress コードを FireDAC コードに置き換えてみましょう。
- Delphi の場合:
if (E is TDBXError) and (Pos('unique key violated', TDBXError(E).Message) > 0) then
MetaBaseDBError(SMb_DataSetInvalidPKeyValue, E);
if (E is EFDDBEngineException) and (EFDDBEngineException(E).Kind = ekUKViolated) then
MetaBaseDBError(SMb_DataSetInvalidPKeyValue, E);
待機カーソル
たとえば、次の dbExpress コードを FireDAC コードに置き換えてみましょう。
- Delphi の場合:
Screen.Cursor := crSQLWait;
try
......
finally
Screen.Cursor := crDefault;
end;
uses
FireDAC.Stan.Factory, FireDAC.UI.Intf;
......
var
oWait: IFDGUIxWaitCursor;
......
FDCreateInterface(IFDGUIxWaitCursor, oWait);
oWait.StartWait;
try
......
finally
oWait.StopWait;
end;
サードパーティ製品との統合
レポート作成ツールや m 層ライブラリなどの多くのサードパーティ製品を使用するには、DAC アダプタ ユニットが必要です。FireDAC 用のアダプタの入手方法については、サードパーティ製品のベンダに問い合わせてください。
低レベル API
FireDAC には、dbExpress API(Data.DBXCommon)に相当するものはありません。dbExpress API(Data.DBXCommon)を使用しているコードは、FireDAC API(DatS レイヤおよび Phys レイヤの API)だけを使ってコーディングし直さなければなりません。詳細は、「全般(FireDAC)」を参照してください。直接の解決策はありません。
ドライバと接続
ドライバおよびクライアント ライブラリの設定
dbExpress には、DriverUnit、DriverPackageLoader、DriverAssemblyLoader、MetaDataPackageLoader、MetaDataAssemblyLoader、GetDriverFunc、LibraryName、LibraryNameOsx など、ドライバ リンク用のパラメータが多数あります。これらに相当するものは FireDAC にはありません。代わりに、FireDAC ドライバは静的にリンクすることも、ビルド済みの FireDAC パッケージを使って動的にリンクすることもできます。この詳細については、「配置(FireDAC)」を参照してください。
dbExpress では、接続パラメータで VendorLib パラメータを指定することができます。FireDAC ではそれをサポートしていません。FireDAC ドライバを構成するには、TFDPhysXxxDriverLink.VendorLib プロパティ値を設定するか、FDDrivers.ini ファイルを使用します。詳細は、「ドライバの構成(FireDAC)」を参照してください。
たとえば、次の dbExpress コードを FireDAC コードに置き換えてみましょう。
- Delphi の場合:
SQLConnection1.Params.Add('VendorLib=' + ExtractFilePath(Application.ExeName) + 'libmysql.dll');
FDPhysMySQLDriverLink1.VendorLib := ExtractFilePath(Application.ExeName) + 'libmysql.dll';
接続の設定
dbExpress では、保存済みの接続パラメータ セットは名前付き接続と呼ばれ、dbxConnections.ini ファイルに保存されます。アプリケーションでこれらの名前付き接続を管理するには、GetConnectionAdmin から返される IConnectionAdmin インターフェイス参照を使用できます。 FireDAC では、保存済みの接続パラメータ セットは接続定義と呼ばれ、FDConnectionDefs.ini ファイルに保存されます(「接続の定義(FireDAC)」を参照)。FDManager コンポーネントを使用すると、接続定義を管理できます。
dbExpress では、実行時に名前付き接続から接続パラメータを(自動的に)読み込むには、アプリケーションで ConnectionName と LoadParamsOnConnect または LoadParamsFromIniFile を使用します。 FireDAC アプリケーションでは、ConnectionDefName のみ設定します。
たとえば、次の dbExpress コードを FireDAC コードに置き換えてみましょう。
- Delphi の場合:
SQLConnection1.ConnectionName := 'IBConn';
// loads parameters of 'IBConn' named connection from dbxConnections.ini
SQLConnection1.LoadParamsFromIniFile;
SQLConnection1.Connected := True;
// will load parameters of 'IBConn' connection definition from FDConnectionDefs.ini
FDConnection1.ConnectionDefName := 'IBConn';
FDConnection1.Connected := True;
データベースへのログイン
dbExpress では VCL または FireMonkey の標準のログイン ダイアログを使用します。FireDAC では、TFDGUIxLoginDialog コンポーネントを使用し TFDConnection.LoginDialog にこのコンポーネントを設定する必要があります(詳細は、「接続の確立(FireDAC)」を参照)。
TFDConnection.OnLogin イベントは TSQLConnection.OnLogin イベントのパラメータ リストと互換性がありません。
(FireDAC_Migrate_DBX.txt の適用後に)次のハンドラ宣言を FireDAC コードに変更する必要があります。
- Delphi の場合:
procedure TMyDataModule.dbLogin(Database: TFDConnection; LoginParams: TStrings);
begin
LoginParams.Values['User_Name'] := 'me';
LoginParams.Values['Password'] := 'pwd';
end;
procedure TMyDataModule.dbLogin(Database: TFDCustomConnection; LoginParams: TFDConnectionDefParams);
begin
LoginParams.Values['User_Name'] := 'me';
LoginParams.Values['Password'] := 'pwd';
end;
トランザクションの制御
dbExpress のトランザクション制御 API では、複数のアクティブなネストしていないトランザクションをサポートしています。複数のトランザクションの場合には、ID ベースのアプローチが使用されます。
FireDAC では、複数のアクティブなネストしたトランザクションをサポートしています(詳細は、「トランザクションの管理(FireDAC)」を参照)。 アプリケーションでは、複数のトランザクションの場合には、同一の TFDConnection に接続された複数の TFDTransaction を使用することができます。ネストしたトランザクションの場合には、StartTransaction/Commit/Rollback の呼び出しをネストすることができます。
FireDAC.DBX.Migrate ユニットでは、dbExpress のトランザクション制御 API をエミュレートしていますが、複数のアクティブなトランザクションをサポートしていません。複数のアクティブなトランザクションをサポートするには、コードを変更する必要があります。
たとえば、次のコードを FireDAC コードに置き換えてみましょう。
- Delphi の場合:
uses
FireDAC.DBX.Migrate;
...
var
oTx1: TFDDBXTransaction;
...
oTx1 := FDConnection1.BeginTransaction;
try
...
FDConnection1.CommitFreeAndNil(oTx1);
except
FDConnection1.RollbackFreeAndNil(oTx1);
raise;
end;
FDTransaction1.StartTransaction;
try
...
FDTransaction1.Commit;
except
FDTransaction1.Rollback;
raise;
end;
追跡
dbExpress の追跡機能は TSQLMonitor コンポーネントと TSQLConnection.TraceCallbackEvent イベント ハンドラに基づいています。 FireDAC の追跡機能は TFDMoniXxxClientLink コンポーネント セットと接続定義パラメータ MonitorBy=Xxx に基づいています(詳細は、「追跡と監視(FireDAC)」を参照)。
どちらのライブラリもこの機能領域では互換性がないので、dbExpress の追跡機能のセットアップは、FireDAC のセットアップに完全に置き換える必要があります。たとえば、FireDAC 接続の追跡結果の出力を有効するには、次のコードを使用します。
- Delphi の場合:
FDMoniRemoteClientLink1.Tracing := True;
FDConnection1.Params.Add('MonitorBy=Remote');
FDConnection1.Connected := True;
接続のメタ情報
dbExpress では、TSQLConnection.MetaData プロパティを通じて、接続固有のメタデータが提供されます。このプロパティは TDBXDatabaseMetaData オブジェクトの参照を返します。 FireDAC では、TFDConnection.ConnectionMetaDataIntf プロパティを通じて、同様のメタデータが提供されます。このプロパティは IFDPhysConnectionMetadata インターフェイスの参照を返します。
TDBXDatabaseMetaData API と IFDPhysConnectionMetadata API は互換性がありません。
データセットとコマンド
全般
dbExpress データセットと FireDAC データセットの大きな違いは次のとおりです。
- dbExpress データセットは単方向データセットです。dbExpress データセットでは、取得されたレコードはキャッシュに格納されません。アプリケーションでは、結果セット内にランダムな位置を設定できません。
- FireDAC データセットはデフォルトでは双方向データセットです。これは FetchOptions.Unidirectional プロパティで制御されます。
- dbExpress データセットのクライアント側機能は非常に限られています。並べ替え、フィルタ処理、範囲、集計などをサポートしていません。
- FireDAC データセットは高度なクライアント側機能を備えています。
- dbExpress データセットは読み取り専用です。レコードの編集、更新内容の自動ポスト、更新内容のキャッシュ処理などをサポートしていません。
- FireDAC データセットは高度な更新機能を備えています。
dbExpress の上記の制限を回避するため、多くの dbExpress アプリケーションでは TDataSetProvider コンポーネントと TClientDataSet コンポーネントを使用します。dbExpress アプリケーションを FireDAC に移行した後は、TDataSetProvider コンポーネントと TClientDataSet コンポーネントを削除して、FireDAC データセットだけを使用する必要があります。
互換性
dbExpress データセット(dbExpress データセット、TDataSetProvider、TClientDataSet を使用する場合)と FireDAC データセットでは、データ処理が少し異なります。
FireDAC データセットの互換性を強制的に持たせるには、FormatOptions.DataSnapCompatibility を True
に設定します。
dbExpress データセットでは、位置によるパラメータ バインディングを使用します。つまり、Params コレクション プロパティに含まれている各パラメータが、SQL コマンド テキスト内のパラメータ マーカーに、名前ではなく位置で照合されます。FireDAC では、名前によるパラメータ バインディングをデフォルトで使用します。
次のような場合には、問題が発生する可能性があります。
- 同じ名前のパラメータ マーカーが SQL コマンド テキストに 2 回以上現れる。
- Params コレクション プロパティ内のパラメータの順序が、SQL コマンド テキスト内のパラメータ マーカーの順序と異なる。
これらの問題を解決するには、以下を検討します。
- SQL コマンド テキストを変更し、すべてのパラメータ マーカーを一意な名前にする。
- FireDAC データセットの Params.BindMode を pbByNumber に設定する。
永続フィールド
永続フィールドを扱う dbExpress アプリケーションについては、さらに調整する必要があります。
dbExpress では、永続フィールドの Origin プロパティと ProviderFlags プロパティを提供も使用もせず、また、データベース ディクショナリにクエリを発行して一意識別フィールドを取得することもありません。FireDAC では、永続フィールドの Origin プロパティと ProviderFlags プロパティを提供し使用します。 移行スクリプト FireDAC_Migrate_DBX.txt では、TField.Origin 値をすべて DFM ファイルから削除します。FireDAC では、Origin が(dbExpress アプリケーションの場合のように)空であれば、フィールド名を使用します。 しかし、ProviderFlags のデフォルト値には pfInKey が含まれておらず、FireDAC ではデータベースにクエリを発行して主キー フィールドを問い合わせることはありません。そのため、一意識別フィールドを取得することができず、さらに以下のいずれかの処置を取る必要があります。
- 永続フィールドを作成し直す。
- ProviderFlags を手動で調整する。
- UpdateOptions.KeyFields を手動で指定する。
TSQLTable
FireDAC の TFDTable は、BDE の TTable と dbExpress の TSQLTable に相当します。 FireDAC への移行中に、すべての TSQLTable を TFDQuery に間違いなく置き換えることをお勧めします。
TSQLDataSet
FireDAC には、TSQLDataSet に直接相当するクラスはありません。
クラスの置換には、次のように、いくつかの選択肢があります。
- TSQLDataSet が "静的" コマンド タイプで使用されている場合は、TFDQuery(「コマンドの実行(FireDAC)」を参照)、TFDStoredProc(「ストアド プロシージャの実行(FireDAC)」を参照)、TFDTable(「テーブルの閲覧(FireDAC)」を参照)のいずれかに置き換えます。
たとえば、次の dbExpress コードを FireDAC コードに置き換えてみましょう。
- Delphi の場合:
SQLDataSet1.CommandType := ctQuery;
SQLDataSet1.CommandText := 'select * from tab';
SQLDataSet1.Open;
SQLDataSet2.CommandType := ctTable;
SQLDataSet2.CommandText := 'tab';
SQLDataSet2.Open;
FDQuery1.SQL.Text := 'select * from tab';
FDQuery1.Open;
FDTable1.TableName := 'tab';
FDTable1.Open;
- TSQLDataSet が "動的" コマンド タイプで使用されている場合は、TFDMemTable、TFDTableAdapter、TFDCommand に置き換えます(TFDCommand はさまざまなコマンドの種類で使用される可能性があります)。
- SetSchemaInfo メソッドを使ってデータベースのメタ情報を取得するのに TSQLDataSet が使用されている場合は、TFDMetaInfoQuery に置き換えます(詳細は「メタデータのクエリ(FireDAC)」を参照)。
たとえば、次の dbExpress コードを FireDAC コードに置き換えてみましょう。
- Delphi の場合:
SQLDataSet1.SetSchemaInfo(stTables, '', '', '');
SQLDataSet1.Open;
SQLDataSet2.SetSchemaInfo(stColumns, 'TAB', '', '');
SQLDataSet2.Open;
FDMetaInfoQuery1.MetaInfoKind := mkTables;
FDMetaInfoQuery1.Open;
FDMetaInfoQuery2.ObjectName := 'TAB';
FDMetaInfoQuery2.Open;