トランザクションとデータ対応コンポーネントを使用して Delphi データベース アプリを作成する好ましい方法

StackOverflow https://stackoverflow.com/questions/3833432

質問

トランザクションとデータ対応コンポーネントを使用して Delphi データベース アプリケーションを作成する望ましい方法は何ですか?

InnoDB テーブルにアクセスし、トランザクション内でマスター詳細のようなことを行うクライアント アプリを作成する必要があります。(一般的な観点から) トランザクションについていくつかの調査を行った後、私は謙虚に、非データ認識コンポーネントと手作業でコーディングされた SQL がトランザクションに「完全に一致する」という結論を下します。しかし、データ対応コンポーネントはそうではありません。お互いのために作られたものではないようです。

トランザクションを使用する必要性は実際にありますが、一方で、データ対応コンポーネントは作業を大幅に簡素化するため、単純に捨てるわけにもいきませんでした。

誰か私に教えてくれませんか?グーグルで調べましたが、有用な答えが見つかりませんでした。おそらく私の英語が十分ではないため、キーワードが限られていると思います。

ところで、私は Delphi 7 を使用しており、現在データ アクセス ライブラリとして UniDAC を評価しています。

ありがとう。

編集

私の質問の一面を説明する例:

2 つの DBGrid があるフォームを想像してください。最初のグリッドは MasterGrid で、その上に次のボタンがあります。追加、編集、削除。2 番目のグリッドは DetailGrid です。ユーザーが「追加」をクリックすると、次のようになります。

  • 接続.StartTransaction
  • Master.Append、Master.Post、Master.Edit (つまり、マスター データセットには自動インクリメント主キーがあり、編集可能になります)
  • ユーザーがマスター レコードを入力し、別のフォームを使用して詳細レコードを追加する編集フォームをモーダルに表示します。
  • ユーザーが [OK] をクリックすると、アプリは Master.Post と Connection.Commit を実行します。ユーザーが [キャンセル] をクリックすると、アプリは Connection.Rollback を実行します。

トランザクションはできるだけ短くする必要があることはわかっていますが、トランザクションはユーザーがフォームに入力する速度と同じくらい短いことが上記でわかります。

データ非対応コンポーネントを使用している場合は、ユーザー入力に基づいてカスタム挿入 SQL を作成し、StartTransaction と Commit の間に SQL を実行します。したがって、非常に短いトランザクションを実現できます。

編集2

皆様のご参加に心より感謝申し上げます。現在のニーズに最も近いソリューションであるため、vcldeveloper からの回答を選択します。

役に立ちましたか?

解決

他の人は、DatasetProvider と ClientDataset の組み合わせを使用してバッチ更新を行うと述べていますが、ADO または UniDAC コンポーネントを使用する場合は、ADO と UniDAC の両方がバッチ更新をサポートしているため、DatasetProvider + ClientDataset の追加の層は必要ありません。

のために ADO, 、あなたがすべきことは設定することです ロックタイプ データセットの ltバッチ楽観的. 。のために UniDAC, 、設定する必要があります キャッシュ更新 財産を 真実.

この変更により、データセットはメモリ内のレコードセットに加えたすべての変更をキャッシュし、呼び出したときにのみそれらをすべてデータベースにまとめて送信するようになります。 更新バッチ メソッド (ADO) または アップデートの適用 方式(UniDAC)。

ここで、ユーザーがマスター データセット内のレコードと、希望するデータ対応コンポーネントを使用して詳細データセット内の任意のレコードを挿入/編集できるようにする必要があります。すべての変更はキャッシュされます。ユーザーの作業が完了したら、新しいトランザクションを開始し、最初にマスター データセットに対して UpdateBatch (UniDAC の場合は applyUpdate) を呼び出し、次に詳細データセットに対して呼び出します。すべてが正常に完了したら、トランザクションをコミットします。

これにより、ClientDataset の追加レイヤーを必要とせずにトランザクションが短くなります。

よろしく

他のヒント

私はあなたの質問を理解して、私は思います。例えばとともにTADODataSetではを開くときデータの10行がデータ認識コンポーネントと、フォーム上で編集するために、あなたは10行(そしておそらく欠失および挿入)のすべてに行われたすべての変更をキャッシュして、1つのバッチとして、それをコミットしたいという状況があります。それは、同じデータを変更し、他のユーザーをブロックするためにあなたは、最初の変更にトランザクションを開くことができません。トランザクションはできるだけ短くする必要があります。

私はスケッチシナリオでやっていることはチェーンで次のコンポーネントを使用します。

TADOConnectionの>>のTADODataSet >> TDataSetProvider >> TClientDataSetの>>のTDataSource >> TDBEditsなど。

これで、すべての変更がTClientDataSetのにキャッシュされ、あなたは1つの、高速トランザクション内のすべての変更を投稿することのメソッドApplyUpdatesメソッドを呼び出すことができます。それは、ネストされたデータセットとの主従(-detail-など)構造のため、複数のTADODataSetsと複数のTClientDataSetsを使用することも可能だというマインド。すべてのマスター・ディテールの変化もキャッシュされ、1回のトランザクションで一括して適用することができます。これを実装に関するすべての詳細については、別の場所で助けとリソースを参照してください。最初は簡単ではありません。あなたはそれを考え出した場合しかし、それは可能性の容易なと申し出トンです。 (オフライン編集、それらを適用する前に、変更を調べるなど。)

大規模なトランザクションを実行する必要性を避けるために、私は データセットプロバイダー そして クライアントデータセット (ローカルでも)。

これを一種のキャッシュとして使用することを検討してください。これにより、両方の長所が得られます。データ対応コントロールを使用すると、UI での作業を簡素化できます。データセットに対するユーザーのアクションは、ClientDataSet (データベース キャッシュの一種) によって「記録」されます。

ユーザーの準備ができたら、 保存 データベースへの変更 (たとえば、請求書データがすべて適切な場所にあるなど) を呼び出すと、 アップデートの適用 データセットのメソッド。

すべてのデータセットがマスター/詳細関係 (プロバイダーによってネストされている) にある最も単純なシナリオでは、プロバイダーが独自にトランザクションを開始してコミット/ロールバックするため、自動的に全か無かの状況になります。

より複雑な関係がある場合は、関連する各 ClientDataSet セットの更新の適用を開始する前に StartTransaction を呼び出し、最後に必要に応じて Commit または Rollback を呼び出すことができます。プロバイダーのロジックは、ApplyUpdates が呼び出されたときに接続にアクティブなトランザクションがある場合、トランザクションを制御していると仮定して、トランザクションに対して何も行わず、データベースに変更をポストするだけです。

運用環境に導入する前に、TClientDataSet と OnReconcileError の処理方法について読んで、このテクノロジを試してみる必要がありますが、私にとっては非常にうまく機能します。

私の2セント。

あなたです絶対に正しいというの書き込みのトランザクションはできるだけ短くすべきであり、ユーザーがフォームを記入している間、それはすべての時間を生きていてはいけません。

は、一般的な解決策は、既に答えとして、中間層(ClientDataSetの)を使用することです。しかし、それが実際に必要とされるずっと前に、あなたのシナリオに本当の問題は、あなたがMaster.AppendとMaster.Postせずにマスターテーブルの自動インクリメント値を得ることができないということであり、その結果、あなたはの書き込みのトランザクションを開始します。

ですから、中間層を使用すると、まだあなたが支持体には、(にINSERTを実行せずに自動インクリメント値を取得するデータベースを考える必要があります短いの書き込みの取引とデータ認識コンポーネントを使用しない場合マスター表)。例では、この機能を完全にサポートするFirebirdのための Firebirdののデータベース、及びFibPlusデータアクセスコンポーネントである。

の必要に応じて

トランザクションは、短いようでなければなりません。問題は、異なるデータベースがロックを処理する方法です。唯一の行レベルのロックを行い、デッドロックにはるかに少ないprobabiltyを持って待つことなく、ロックからすぐに復帰できるデータベース。通常インサートはあまり問題である(コミットされるまで他のユーザーが分離レベルに応じて、新しい行が表示されませんが)、更新および削除がより問題です。 あまりにも頻繁にコミットするだけでなく、「悪い」である可能性があります。変更内容をキャッシュし、単一の操作でそれらを適用することは、別の可能性である - しかし、あなたが原因その間レコードを変更他のユーザーに問題を処理しなければなりません。 「より良い」解決策は何もありません - すべては、実際のニーズによって異なります。記録を維持するいくつかのアプリケーション(および一部のデータベース)のために他の人はいないかもしれないため、okです限り、彼らが変化しているようにロック。バッチ更新は、いくつかのシナリオではなく、他でOKかもしれません。あなたは、あなたのアプリケーションとデータベースのための最高の作品のモデルを選択する必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top