11

基になるデータベースには存在しないが、既存のフィールドから派生できる TDataSet に追加のフィールドを追加する必要があります。計算されたフィールドでこれを簡単に行うことができ、それは完全に機能します。

これらのフィールドを編集して、変更されたデータを書き戻したいと思います。計算を逆にしてデータを既存のフィールドに書き戻すことはできますが、DB コントロールでは計算フィールドを編集できません。

これを可能にするアプローチはありますか?

更新: OK、背景についての詳細。

データセットには、TBytes 表現である blob フィールドがあります。一部のバイトは、既存の DB 編集フィールドで便利な方法で表現できる情報を含むことが識別されます。ただし、すべてのバイトが認識されているわけではないため、TBytes 表現を認識している別のアプリケーションで処理するために、TBytes 表現をそのまま保持する必要があります。このアプリはまた、既存のレコードを変更し、新しいレコードを挿入します。

データセット内の異なるレコードの TBytes は、多くの場合、異なるフィールド表現にマップされますが、データセットにフィルターまたは範囲を設定すると、それらが同じマッピングを持つことが保証されます。

前述したように、既知のバイトを抽出し、計算フィールドを介して文字列、日付、数値などに変換することは問題ありません。これらの値を TBytes に再変換することも可能です。問題は、データセットのナビゲーションをそのまま維持しながら、これらの余分なフィールドを編集可能にすることです。

役立つ場合: 双方向のマッピングを行い、フィールドを公開されたプロパティとして公開するクラスがあります。

4

7 に答える 7

4

答えは、使用しているデータ アクセス コンポーネントによって異なります。私は Anydac を使用しており、fkInternalCalc フィールドをサポートしています。これは、手動で編集したのと同じように計算される場合があります。

于 2011-03-19T09:14:27.763 に答える
3

ClientDataSetでも同様の問題が発生しました。データベースのフィールドをシミュレートできるように、SQL-Stmtでダミーフィールドを使用してこの問題を解決しました。

私の質問を参照してください

于 2011-03-18T12:16:52.550 に答える
3

計算フィールドは定義上、読み取り専用であり、クライアントで値が計算されると思います。あなたが望むものは、おそらく更新可能なビューによって実装される可能性があります。計算フィールドを既に使用してビューを定義することができます。これらはサーバー上の SQL で計算されます。また、更新トリガー、場合によっては挿入トリガーも使用して、逆の計算を実行できます。次に、クライアントから、ビューをテーブルのように透過的に使用できます。

于 2011-03-18T12:04:19.827 に答える
1

TDatasetProvider.OnGetRecords (これがイベントの正しい名前かどうかは覚えていません) を使用して、Clientdataset に送信されるデータパケットを変更できます。

もちろん、TOndrej が言ったように、ApplyUpdates ハンドラーでそれらを処理する必要があります。

于 2011-03-18T13:39:00.213 に答える
0

私たちのデータベース設計では、一部の値は別の列 (以下で参照) に対するパーセンテージですがoMean、他の float 値は絶対値として格納されます。顧客は後に、すべてのフィールドに対して両方のオプション (rel. と abs.) を希望したため、 から派生した次のクラスを考え出しましたTFloatField。すべての TDataSet の子孫に対して機能するはずです。

unit EditableCalcFloatField;

interface

uses
  db, classes;

type
  TEditableCalcFloatField = class(TFloatField)
  public
    oAbs, oRel, oMean: TField;
  protected
    function GetCanModify: Boolean; override;
    procedure SetAsFloat(Value: Double); override;
  end;

implementation

function TEditableCalcFloatField.GetCanModify: Boolean;
begin
  Result := oMean.AsFloat <> 0;
  if not Result then Exit;
  Result := (oAbs <> nil) or (oRel <> nil);
end;

procedure TEditableCalcFloatField.SetAsFloat(Value: Double);
var
  fMean                                 : Double;
begin
  inherited;

  if DataSet.State in [dsEdit, dsInsert] then begin
    fMean := oMean.AsFloat;
    if fMean = 0 then Exit;
    if oAbs <> nil then
      oAbs.AsFloat := Value / 100 * fMean
    else
      oRel.AsFloat := Value / fMean * 100;
  end;
end;

end.

FormCreateパッケージなしで使用するには、データセットを開く前に でフィールドを作成する必要があります。

with TEditableCalcFloatField.Create(Self) do
begin
  oAbs := sqlMerkmaleYourAbsoluteColumn;
  DisplayLabel := sDisp;
  oMean := sqlMerkmaleAssignedValue_Mean;
  Calculated := True;
  FieldName := 'R' + oAbs.FieldName;
  DataSet := sqlMerkmale;
end;

もちろん、その内容はOnCalcFieldsイベントまたはユーザーが設定できます。

于 2013-04-17T11:02:23.893 に答える
0

Woll2Woll の infopower コンポーネント (TwwDBEdit をテストしたところです) は、そのようなことを可能にします。だから私はあなたが TDBEdit レベル (または TFieldDataLink レベル) にあるブロックは何でも考えます。

TwwDBEdit で何が違うのか、私にはわかりません。(そして、ライセンス契約がここに投稿することを許可するかどうかはわかりません...)。

于 2011-03-18T14:46:12.637 に答える
0

「Select *, 0 as TempField from MyTable」で TQuery の子孫 (MyQuery) を使用する

Procedure MyQueryAfterOpen(Dataset:TDataSet);
Begin
    DataSet.FieldByName('TempField').ReadOnly := False;
End;

現在は編集可能な一時フィールドです

于 2015-09-15T06:43:55.713 に答える