简体   繁体   English

如何在TDataSet中实现“可写计算”字段?

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

I am in the need to add additional fields to a TDataSet that don't exist in the underlying database but can be derived from existing fields. 我需要在TDataSet中添加其他字段,这些字段在底层数据库中不存在,但可以从现有字段派生。 I can easily do this with caclulated fields and that works perfectly. 我可以轻松地使用caclulated字段做到这一点,并且完美无缺。

Now I want to edit these fields and write the changed data back. 现在我想编辑这些字段并将更改的数据写回。 I can reverse the calculation to write the data back into the existing fields, but the DB controls just don't let me edit calculated fields. 我可以反转计算以将数据写回现有字段,但DB控件只是不允许我编辑计算字段。

Is there any approach that allows me to do this? 是否有任何方法可以让我这样做?

Update: Ok, some more details about the background. 更新:好的,有关背景的更多细节。

The dataset has a blob field, which is a TBytes representation. 数据集有一个blob字段,它是一个TBytes表示。 Some of the bytes are identified to contain information that can be represented in a convenient way with existing DB edit fields. 一些字节被识别为包含可以用现有DB编辑字段以方便的方式表示的信息。 Not all of the bytes are known, though, so the TBytes representation has to be kept as it is for processing through another application that knows about it. 但是,并非所有字节都是已知的,因此TBytes表示必须保持原样,以便通过另一个了解它的应用程序进行处理。 This app also modifies existing and inserts new records. 此应用程序还修改现有和插入新记录。

The TBytes of different records in the dataset often map to different fields representations, although setting a filter or range on the dataset will ensure that they have the same mapping. 数据集中不同记录的TByte经常映射到不同的字段表示,尽管在数据集上设置过滤器或范围将确保它们具有相同的映射。

As I said, extracting the known bytes and convert it into strings, dates, numbers and so on via calculated fields is no problem. 正如我所说,提取已知字节并通过计算字段将其转换为字符串,日期,数字等是没有问题的。 Reconverting those values into the TBytes is also possible. 将这些值重新转换为TBytes也是可能的。 The problem is making those extra fields editable, while keeping the dataset navigation intact. 问题是使这些额外的字段可编辑,同时保持数据集导航不变。

If it helps: We have classes that do the bidirectional mapping, exposing the fields as published properties. 如果它有帮助:我们有类进行双向映射,将字段公开为已发布的属性。

The answer depends on a data access components you are using. 答案取决于您使用的数据访问组件。 I am using Anydac and it support fkInternalCalc fields, which may be as calculated as manually edited. 我正在使用Anydac,它支持fkInternalCalc字段,可以像手动编辑一样计算。

I think calculated fields are by definition read-only, with values calculated on the client. 我认为计算字段按照定义是只读的,在客户端上计算值。 What you want could probably be implemented by an updatable view. 您想要的可能是可更新视图。 You could define the view with calculated fields already - these would be calculated in SQL on the server - and an update trigger, maybe an insert trigger, too - to perform the reverse calculation. 您可以使用计算字段定义视图 - 这些将在服务器上以SQL计算 - 以及更新触发器,也可以是插入触发器 - 以执行反向计算。 Then from the client you could use the view transparently like a table. 然后,从客户端,您可以像表一样透明地使用视图。

I had similar Issue with a ClientDataSet, i have solved this issue using dummy fileds on the SQL-Stmt so i could simulate the Fields in the Database. 我有一个与ClientDataSet类似的问题,我已经在SQL-Stmt上使用虚拟文件解决了这个问题,所以我可以模拟数据库中的字段。

See my Question 看我的问题

You can use TDatasetProvider.OnGetRecords (doesn't remember if this is the correct name of the event) and modify the datapacket sent to the Clientdataset. 您可以使用TDatasetProvider.OnGetRecords(不记得这是否是事件的正确名称)并修改发送到Clientdataset的数据包。

Of course, you'll have to deal with them on an ApplyUpdates handler, as TOndrej said. 当然,正如TOndrej所说,你必须在ApplyUpdates处理程序上处理它们。

In our database design, some values are percentages relative to another column (called oMean below), whereas other float values are stored as absolutes. 在我们的数据库设计中,一些值是相对于另一列的百分比(在下面称为oMean ),而其他浮点值则存储为绝对值。 Our customers later wanted both options (rel. and abs.) for all fields, so we came up with the following class derived from TFloatField . 我们的客户后来想要所有字段的两个选项(rel。和abs。),所以我们想出了从TFloatField派生的以下类。 It should work for all TDataSet descendants. 它应该适用于所有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.

To use it without a package, you have to create the field in FormCreate , before the dataset is opened: 要在没有包的情况下使用它,您必须在打开数据集之前在FormCreate创建字段:

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

And of course, its contents can be set either in the OnCalcFields event or by the user. 当然,其内容可以在OnCalcFields事件中设置,也可以由用户设置。

Use a TQuery descendant (MyQuery) with 'Select *, 0 as TempField from MyTable' 使用TQuery后代(MyQuery)和'Select *,0作为来自MyTable的TempField'

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

It is now an editabe temporary field 它现在是一个可编辑的临时字段

Woll2Woll's infopower components (I just tested their TwwDBEdit) allow to do such thing. Woll2Woll的infopower组件(我刚刚测试了他们的TwwDBEdit)允许这样做。 So I would think whatever blocks you is at the TDBEdit level (or at the TFieldDataLink level). 所以我认为你在TDBEdit级别(或TFieldDataLink级别)阻止你。

What exactly differs in TwwDBEdit, I don't know. 在TwwDBEdit中究竟有什么不同,我不知道。 (And I'm not sure the license agreement would allow me to post here...). (而且我不确定许可协议是否允许我在这里发帖......)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM