問題タブ [tdataset]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
delphi - Delphi: OnBeforePost イベントで TDataSet.Post をキャンセルする
メインのデータ入力画面では、OnBeforePost イベントに OK/Cancel ダイアログがあります。
- OK、物事を自然に任せましょう
- 今すぐキャンセルすると
Dataset.Cancel;
これは、変更をロールバックし、データセットをブラウズ モードにします。
ほとんどのクライアントはこれで問題ありませんが、次のように変更できるかどうか尋ねられました。
- キャンセル、投稿を中止し、現在の変更を維持したまま編集モードにとどまります。
キャンセルする場合は、キャンセル ボタンを使用できます。
ソースを見ると、procedure TDataSet.Post;
この方法でイベントを使用することはできません。
これを行う方法について何か考えがある人はいますか?
フォローアップ: これは私が今それを処理するために選択した方法です
delphi - フィルタ文字列に対して TDataSet 行をチェックする
メモリ TDataSet の子孫でDevExpress TdxMemDataを使用しています。Filtered: Boolean および Filter: String プロパティがありますが、OnFilterRecord イベントの Accept パラメータの結果に依存する代わりに、実際にはそれらを自動的に処理するようには見えません。
したがって、私が探しているのは、フィルター テキストを解析してデータセットに適用する方法です (おそらく、TdxMemData または DevExpress のコード スイートのどこかにあります)。
理想的には、フィルターに対して個々の行をテストして、データセットからフィルター処理せずに一致するかどうかを確認する方法が必要です (フィルターに一致する行を強調表示したい)。
フィルター文字列の例:
したがって、ネストされた and と or があります。実際には、DevExpress TcxDBFilterControl によって構築されます。
私が見逃している単純なものがあることを本当に望んでいます。
更新: DevExpress でチケットを開いて、何らかの種類のソリューションがサポートされているかどうかを確認しました。TdxMemDataでの フィルタリングをサポートしていないという彼らのストックアンサーを見つけました。
delphi - TFieldをnull許容として宣言するにはどうすればよいですか?
ADOベースのクライアントデータセットを設定しています。TIntegerFieldにnull値を挿入しようとすると、Postで次のようになります。Project raised exception class EDatabaseError with message 'Non-nullable column cannot be updated to Null'.
TFieldをnull許容として設定する方法を見たことはありますが、どこでどのように設定するかを思い出せません。誰かがこれを修正する方法を知っていますか?
編集:フィールドは設計時に必須= falseに設定され、実行時にまだfalseであることを確認しましたが、それでもエラーが発生します。
delphi - DBGrid で列を移動すると、添付された DataSet フィールドが移動するようです
先週、私が予期していなかったことがわかりました。以下に説明します。なぜこれが起こるのか、私は興味があります。TDataSet クラスの内部的なものですか、TDBGrid のアーティファクトですか、それとも何か他のものですか?
開いている ClientDataSet のフィールドの順序が変更されました。具体的には、FieldDefs を使用してその構造を定義した後、CreateDatatSet を呼び出して、コードで ClientDataSet を作成しました。この ClientDataSet の構造の最初のフィールドは、StartOfWeek という名前の Date フィールドでした。ほんの少し後、StartOfWeek フィールドが ClientDataSet.Fields[0] の 0 番目の位置にあると仮定して私が書いたコードは、StartOfWeek フィールドが ClientDataSet の最初のフィールドではなくなったため、失敗しました。
調査の結果、ClientDataSet のすべてのフィールドが、特定の時点で、ClientDataSet が作成された時点の元の構造とは異なる位置に表示される可能性があることがわかりました。私はこれが起こる可能性があることを知りませんでした.Googleで検索しても、この影響についての言及はありませんでした.
起こったことは魔法ではありませんでした。フィールドはそれ自体で位置を変更したり、コードで行ったことに基づいて変更したりしませんでした。フィールドが ClientDataSet 内の位置を物理的に変更したように見える原因は、ユーザーが ClientDataSet がアタッチされている DbGrid 内の列の順序を (もちろん、DataSource コンポーネントを介して) 変更したためです。Delphi 7、Delphi 2007、および Delphi 2010 でこの効果を再現しました。
この効果を実証する非常に単純な Delphi アプリケーションを作成しました。これは、1 つの DBGrid、DataSource、2 つの ClientDataSet、および 2 つの Button を持つ単一のフォームで構成されています。このフォームの OnCreate イベント ハンドラは次のようになります。
[ClientDataSet 構造を表示] というラベルの付いた Button1 には、次の OnClick イベント ハンドラーが含まれています。
移動フィールド効果を示すには、このアプリケーションを実行し、[ClientDataSet 構造を表示] というラベルの付いたボタンをクリックします。次のようなものが表示されるはずです。
次に、DBGrid の列をドラッグして、フィールドの表示順序を並べ替えます。[ClientDataSet 構造を表示] ボタンをもう一度クリックします。今回は、次のようなものが表示されます。
この例で注目に値するのは、DBGrid の列が移動されていることですが、ClientDataSet.Field[0] にあったフィールドが 1 つの位置にあるように、ClientDataSet のフィールドの位置に明らかな影響があることです。ポイントは、すぐにそこにあるとは限りません。残念ながら、これは明確に ClientDataSet の問題ではありません。BDE ベースの TTable と ADO ベースの AdoTable で同じテストを実行したところ、同じ結果が得られました。
DBGrid に表示されている ClientDataSet のフィールドを参照する必要がない場合は、この影響について心配する必要はありません。残りの皆さんのために、いくつかの解決策を考えることができます。
必須ではありませんが、この問題を回避するための最も簡単な方法は、ユーザーが DBGrid 内のフィールドを並べ替えられないようにすることです。これは、DBGrid の Options プロパティから dgResizeColumn フラグを削除することで実行できます。このアプローチは効果的ですが、ユーザーの観点からすると、潜在的に価値のある表示オプションが排除されます。さらに、このフラグを削除すると、列の並べ替えが制限されるだけでなく、列のサイズ変更が防止されます。(列のサイズ変更オプションを削除せずに列の並べ替えを制限する方法については、http://delphi.about.com/od/adptips2005/a/bltip0105_2.htm を参照してください。 )
2 番目の回避策は、DataSet のフィールドをリテラル位置に基づいて参照しないようにすることです (これが問題の本質であるため)。つまり、Count フィールドを参照する必要がある場合は、DataSet.Fields[2] を使用しないでください。フィールドの名前がわかっている限り、DataSet.FieldByName('Count') のようなものを使用できます。
ただし、FieldByName の使用にはかなり大きな欠点が 1 つあります。具体的には、このメソッドは、DataSet の Fields プロパティを反復処理してフィールドを識別し、フィールド名に基づいて一致を探します。これは FieldByName を呼び出すたびに行われるため、大きな DataSet をナビゲートするループなど、フィールドを何度も参照する必要がある状況では避けるべきメソッドです。
フィールドを繰り返し (そして何度も) 参照する必要がある場合は、次のコード スニペットのようなものを使用することを検討してください。
3 番目の解決策がありますが、これは、元の例のように、DataSet が ClientDataSet である場合にのみ使用できます。このような状況では、元の ClientDataSet のクローンを作成すると、元の構造を持つことができます。その結果、0 番目の位置に作成されたフィールドは、ClientDataSets データを表示する DBGrid に対してユーザーが行った操作に関係なく、その位置に残ります。
これは、Show Cloned ClientDataSet Structure というラベルの付いたボタンの OnClick イベント ハンドラーに関連付けられている次のコードで示されています。
このプロジェクトを実行し、[複製された ClientDataSet 構造を表示] というラベルの付いたボタンをクリックすると、ここに示すように、ClientDataSet の真の構造が常に取得されます。
補遺:
基になるデータの実際の構造は影響を受けないことに注意することが重要です。具体的には、DBGrid 内の列の順序を変更した後、ClientDataSet の SaveToFile メソッドを呼び出すと、保存された構造は元の (真の内部) 構造になります。また、ある ClientDataSet の Data プロパティを別の ClientDataSet にコピーすると、コピー先の ClientDataSet にも真の構造が表示されます (これは、コピー元の ClientDataSet を複製したときに見られる効果と同様です)。
同様に、TTable や AdoTable など、他のテスト済みのデータセットにバインドされた DBGrid の列の順序を変更しても、実際には基になるテーブルの構造には影響しません。たとえば、Delphi に同梱されている customer.db サンプル Paradox テーブルからのデータを表示する TTable は、実際にはそのテーブルの構造を変更しません (また、期待することもありません)。
これらの観察結果から結論できることは、DataSet 自体の内部構造は損なわれていないということです。その結果、DataSet の構造の二次表現がどこかにあると想定する必要があります。また、DataSet に関連付ける必要があります (DataSet のすべての使用でこれが必要なわけではないため、やり過ぎのように思われます)、DBGrid に関連付ける必要があります (DBGrid がこの機能を使用しているため、これはより理にかなっていますが、そうではありません)。 TField の並べ替えが DataSet 自体で持続するように見えるという観測によってサポートされています)、または別のものです。
もう 1 つの方法は、効果を TGridDataLink に関連付けることです。これは、複数行対応コントロール (DBGrid など) にデータ認識を提供するクラスです。ただし、このクラスは DataSet ではなくグリッドに関連付けられているため、この説明も拒否する傾向があります。これもまた、効果が DataSet クラス自体で持続するように見えるためです。
元の質問に戻ります。この効果は TDataSet クラスの内部にあるものですか、TDBGrid のアーティファクトですか、それとも何か他のものですか?
以下のコメントの1つに追加したことをここで強調することも許可してください. 何よりも、私の投稿は、列の順序を変更できる DBGrid を使用している場合、TField の順序も変更される可能性があることを開発者に認識させるように設計されています。このアーティファクトは、断続的で重大なバグを引き起こす可能性があり、特定と修正が非常に困難になる可能性があります。いいえ、これは Delphi のバグではないと思います。機能するように設計されているため、すべてが機能していると思います。私たちの多くが、この動作が発生していることに気づいていなかっただけです。今、私たちは知っています。
delphi - FIndKeyの結果がFalseの場合、レコードを返しませんか?
TDataSet.FindKeyを使用すると、レコードを見つけることができます。Trueの場合、データセットカーソルは見つかったレコードに配置されます。Falseになると、カーソルは移動しません。これにより、FindKeyが発行される前のレコードデータがデータ対応コンポーネントに表示されます。
FindKeyの結果をコーディングして、空のレコードを返すにはどうすればよいですか?
更新:(それは習慣であり、それ以上のフィードバックを思いとどまらせたくなかったので、正しい答えを選択する前に数日待っていました。)正しい答えはマルセロからのものであると私は信じていますが、この状況に取り組むためのいくつかの提案がありましたカーソルをレコード上に置かないようにすることはできません。いくつかの回避策が提案されました。私は自分のものを選びました。それは次のようになりました:
私が行ったことは、実際のデータにはなり得ないインデックスを使用して、ダミーの空白のレコードを作成することです。つまり、最初のインデックス値が-1になることはありません。最初の検索が空になると、FindKeyはこの空のレコードにカーソルを置きます。これは私が求めていた視覚効果を提供します。
database - MVCパラダイムを使用したデータベースアプリケーション
従来のDelphiデータベースアプリケーションには、TDataSourcesを介してTDataSetsに接続されたデータ対応のビジュアルコントロールのセットであるフォームがあります。MVCモデルを使用してデータベースアプリケーションを設計する場合、TDataSetコンポーネントをどこに配置しますか?それらはフォームにとどまり、したがってビューの一部である必要がありますか?または、それらをモデルオブジェクト内にカプセル化する必要がありますか?後者の場合、どのようにビジュアルコンポーネントにバインドできますか?
database - TDataset Delphiで2つのレコードを交換する最良の方法は?
一般的に Delphi とデータベース プログラミングは初めてですが、TDataset 内のレコードを交換するより良い方法があるかどうか知りたいですか? いくつかのヘルプを読みましたが、明白な方法が見つかりません。現在、レコードが Eof マーカーに到達するまでデータセットを下に移動する手順を実装しています。ただし、データの最後のレコードに到達すると、奇妙なエラーが発生します。私が持っているのは、アクティブなレコードをジャグリングしながらデータなどを保持しようとする標準的な配列スタイルのスワップ ルーチンを実装したことだけです。
これまでのコード
delphi - 設計時にフォームにTDataSetを埋め込む
データベースサーバー上にそのリストを描画するための実際のテーブルがなくても、デルファイのTDBLookupComboBoxにListSourceを提供する方法を探しています。コンボボックスのDataFieldは、「A」=「運転免許証」、「B」=「パスポート」、「C」=「図書館カード」などのコード化された値を含む1文字のフィールドです。テーブルにはA、B、またはCのみが含まれていること。アプリケーションは、GUIに「運転免許証」を表示する責任があります。通常、データベースにはルックアップテーブルがありますが、このデータベースにはルックアップテーブルがなく、追加できません。私の考えでは、DBルックアップコントロールのDataSourceとListSourceは同じデータベースである必要はないため、ルックアップデータを含む小さなテーブルをフォームで定義できる場合は、それを使用できます。実際のデータベーステーブルは必要ありません。
TDataSetを実際のデータファイルを背後に持たずにフォーム上で定義できるようにするデルファイコンポーネントを知っている人はいますか?
delphi - Delphi、TcxGrid または TDataSet で最速のレコード アクセス方法は何ですか
Delphi 2007 と TcxGrid を使用して、ファイル ライブラリの内容を表示しています。データベースには、ファイルの種類、名前、パス、および拡張子に関する情報が格納されています。
テストでは、TDataSet を介して 1700 レコードをグリッドにロードしています。また、まだ計算する必要がある 3 つのフィールドをグリッドに追加します。それらは、ファイルが存在するかどうか、ファイルのサイズ、および変更日です。
私の目標は、保存されているすべての情報をユーザーに表示し (これはうまく機能し、高速です)、バックグラウンド スレッドで他の 3 つのデータ フィールドの情報を見つけて、それらを TcxGrid に挿入することです。この質問は、私が行っているスレッド化とはほとんど関係がありません。その正常に動作します。
私の問題は、既に構築されているグリッド内のフィールドにアクセスすると、アクセスすると非常に遅くなることです。私は2つの異なる方法を試しました...
Grid.DataController.Values[RecordIndex,FieldIndex] - しかし、これは変種であり、それが非常に遅い理由だと思います
Grid.DataController.DataSet.FindFirst Grid.DataController.DataSet.FindNext Grid.DataController.DataSet.Fields[FieldIndex] しかし、この「シーク」メソッドを使用すると、最初に試した方法と同じくらい遅くなります。Locate と moveby も遅いです。
長い質問ですが、レコードにアクセスする最速の方法は何ですか?
delphi - レコードが TDataSet に挿入されたことを確認するにはどうすればよいですか?
TDataSet または TObjectList の内容を表示するグリッド コントロールを作成しています。TDataSet のみをサポートする必要がある場合、物事は非常に単純です。
- TDataLink の子孫を介してデータセットにリンクします。
- グリッドのコンテンツを描画する場合、その TDataLink にバッファリングされたレコードを使用して、必要なものを描画できます。
- TDataSet 内の行を表すために個別のオブジェクトをどこかに置く必要はありません。これは、常にバッファ内の行を描画するだけだからです。
私の場合、他のいくつかのソースからもデータを受け入れる必要があります。つまり、各行を表すオブジェクトが必要でした (これも、コントロールにかなりの数の行の状態が必要だったためです)。
しかし、これは上記のモデルで問題を引き起こします。各行を表すオブジェクトがあるため、TDataSet でレコードが追加または削除されたときに通知を受ける必要があります。そして、私はそれを行う方法がわかりません。
明らかに、データセット イベントにフックしたくありません。それらは既に使用されている可能性があり、TDataLink はコントロールとデータセットの間のメディエーターになることを意図しています。また、DataEvent 仮想メソッドを使用しようとしても失敗しました。レコードが追加/削除されているかどうかがわからないためです。
何か案は?