簡體   English   中英

如何在TDataSet中實現“可寫計算”字段?

[英]How can I implement “writable calculated” fields in a TDataSet?

我需要在TDataSet中添加其他字段,這些字段在底層數據庫中不存在,但可以從現有字段派生。 我可以輕松地使用caclulated字段做到這一點,並且完美無缺。

現在我想編輯這些字段並將更改的數據寫回。 我可以反轉計算以將數據寫回現有字段,但DB控件只是不允許我編輯計算字段。

是否有任何方法可以讓我這樣做?

更新:好的,有關背景的更多細節。

數據集有一個blob字段,它是一個TBytes表示。 一些字節被識別為包含可以用現有DB編輯字段以方便的方式表示的信息。 但是,並非所有字節都是已知的,因此TBytes表示必須保持原樣,以便通過另一個了解它的應用程序進行處理。 此應用程序還修改現有和插入新記錄。

數據集中不同記錄的TByte經常映射到不同的字段表示,盡管在數據集上設置過濾器或范圍將確保它們具有相同的映射。

正如我所說,提取已知字節並通過計算字段將其轉換為字符串,日期,數字等是沒有問題的。 將這些值重新轉換為TBytes也是可能的。 問題是使這些額外的字段可編輯,同時保持數據集導航不變。

如果它有幫助:我們有類進行雙向映射,將字段公開為已發布的屬性。

答案取決於您使用的數據訪問組件。 我正在使用Anydac,它支持fkInternalCalc字段,可以像手動編輯一樣計算。

我認為計算字段按照定義是只讀的,在客戶端上計算值。 您想要的可能是可更新視圖。 您可以使用計算字段定義視圖 - 這些將在服務器上以SQL計算 - 以及更新觸發器,也可以是插入觸發器 - 以執行反向計算。 然后,從客戶端,您可以像表一樣透明地使用視圖。

我有一個與ClientDataSet類似的問題,我已經在SQL-Stmt上使用虛擬文件解決了這個問題,所以我可以模擬數據庫中的字段。

看我的問題

您可以使用TDatasetProvider.OnGetRecords(不記得這是否是事件的正確名稱)並修改發送到Clientdataset的數據包。

當然,正如TOndrej所說,你必須在ApplyUpdates處理程序上處理它們。

在我們的數據庫設計中,一些值是相對於另一列的百分比(在下面稱為oMean ),而其他浮點值則存儲為絕對值。 我們的客戶后來想要所有字段的兩個選項(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事件中設置,也可以由用戶設置。

使用TQuery后代(MyQuery)和'Select *,0作為來自MyTable的TempField'

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

它現在是一個可編輯的臨時字段

Woll2Woll的infopower組件(我剛剛測試了他們的TwwDBEdit)允許這樣做。 所以我認為你在TDBEdit級別(或TFieldDataLink級別)阻止你。

在TwwDBEdit中究竟有什么不同,我不知道。 (而且我不確定許可協議是否允許我在這里發帖......)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM