9

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

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

トランザクションを使用する必要が本当にありますが、一方で、データ対応コンポーネントは非常に単純化されているため、単に破棄することはできませんでした。

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

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

ありがとうございました。

編集

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

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

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

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

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

編集2

皆様のご参加に感謝申し上げます。それが私の現在のニーズに最も近い解決策であるため、私はvcldeveloperから答えを選びます。

4

5 に答える 5

5

私はあなたの質問を理解していると思います。たとえば、フォーム上で編集する10行のデータを含むTADODataSetを開き、データベース対応コンポーネントを使用する場合、10行すべてに加えられたすべての変更(および場合によっては削除と挿入)をキャッシュしたい場合があります。 1つのバッチとしてコミットします。最初の変更でトランザクションを開くことはできません。これは、他のユーザーが同じデータを変更するのをブロックするためです。トランザクションはできるだけ短くする必要があります。

スケッチシナリオで私が行うことは、チェーンで次のコンポーネントを使用することです。

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

これで、すべての変更がTClientDataSetにキャッシュされ、そのメソッドApplyUpdatesを呼び出して、すべての変更を1つの高速トランザクションに投稿できます。ネストされたデータセットを持つmaster-detail(-detail-etc)構造に対して、複数のTADODataSetsと複数のTClientDataSetsを使用することも可能であることに注意してください。すべてのマスター/詳細の変更は、1つのトランザクションで1つのバッチにキャッシュおよび適用することもできます。これを実装するためのすべての詳細については、他の場所のヘルプとリソースを参照してください。最初は簡単ではありません。しかし、あなたがそれを理解した場合、それは簡単であり、たくさんの可能性を提供します。(オフライン編集、変更を適用する前の調査など)

于 2010-09-30T18:58:03.667 に答える
4

DatasetProviderとClientDatasetの組み合わせを使用してバッチ更新を行うことについて言及したものもありますが、ADOまたはUniDACコンポーネントを使用する場合は、ADOとUniDACの両方がバッチ更新をサポートしているため、DatasetProvider+ClientDatasetの追加レイヤーは必要ありません。

ADOの場合、データセットのLockTypeltBatchOptimisticに設定する必要があります。UniDACの場合、 CacheUpdateプロパティをTrueに設定する必要があります。

この変更により、データセットはメモリ内のレコードセットで行ったすべての変更をキャッシュし、UpdateBatchメソッド(ADO)またはApplyUpdatesメソッド(UniDAC)を呼び出した場合にのみ、それらをまとめてデータベースに送信します。

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

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

よろしく

于 2010-10-01T02:27:22.437 に答える
3

大規模なトランザクションを実行する必要性を回避するために、DataSetProvidersClientDatasetsを(ローカルでも)使用します。

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

ユーザーが変更をデータベースに保存する準備ができたら(たとえば、請求書データがすべて揃ったら)、データセットのApplyUpdatesメソッドを呼び出します。

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

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

TClientDataSetと、OnReconcileErrorの処理方法を読み、本番環境に配置する前にテクノロジを試してみる必要がありますが、私にとっては非常にうまく機能します。

私の2セント。

于 2010-09-30T21:52:55.643 に答える
1

書き込みトランザクションは可能な限り短くする必要があり、ユーザーがフォームに入力している間は常に有効である必要はありません。

すでに回答したように、一般的な解決策は、中間層(ClientDataSet)を使用することです。ただし、シナリオの実際の問題は、Master.AppendとMaster.PostがないとMasterテーブルの自動インクリメント値を取得できないため、実際に必要になるずっと前に書き込みトランザクションを開始することです。

したがって、中間層を使用せずに、短い書き込みトランザクションでデータベース対応コンポーネントを使用する場合は、(マスターテーブルへの)INSERTを実行せずに自動インクリメント値の取得をサポートするデータベースを検討する必要があります。例はFirebirdデータベースであり、FirebirdのFibPlusデータアクセスコンポーネントはこの機能を完全にサポートしています。

于 2010-10-01T00:38:45.700 に答える
0

トランザクションは必要なだけ短くする必要があります。問題は、さまざまなデータベースがロックを処理する方法です。行レベルのロックのみを実行し、待機せずにロックからすぐに戻ることができるデータベースでは、デッドロックが発生する可能性がはるかに低くなります。通常、挿入の問題は少なくなります(ただし、分離レベルによっては、コミットされるまで他のユーザーには新しい行が表示されません)。更新と削除の方が問題があります。頻繁にコミットすることも「悪い」可能性があります。変更をキャッシュして単一の操作で適用することも可能ですが、他のユーザーがレコードを変更することによる問題を処理する必要があります。「より良い」解決策はありません-すべてが実際のニーズに依存します。一部のアプリケーション(および一部のデータベース)では、変更されている限りレコードをロックしたままにしておくことは問題ありませんが、そうでない場合もあります。バッチ更新は、一部のシナリオでは問題なく、他のシナリオでは問題がない場合があります。

于 2010-09-30T20:59:37.910 に答える