问题 可以在delphi数据集中创建虚假数据字段吗?


我想在DataSet(而不是ClientDataSet)中创建一个'假'数据字段:

  • 该字段不应存储在db中
  • 它不是计算字段(应允许用户输入输入数据)
  • 该字段具有业务逻辑含义,因此在用户更新其值后,它应更新其他字段(使用OnFieldChange事件)

我知道我可以有一个简单的无dbaware控件,捕获它的OnChange事件并在那里执行计算(或调用DataSet所在的DataModule函数)但我认为如果我可以重新利用数据集自动绑定db-更干净ware控件和数据集事件..

这样,Form(Presentation)和DataModule(Model)之间的唯一连接就是DataSet(更少的耦合)。

PD:我正在使用fibplus,我认为解决方案(如果有的话)将处于VCL级别。

谢谢!


8740
2017-11-03 15:56


起源

对非db内容使用DB Aware控件实际上是次优的。还有其他方法可以避免连接您不想连接的内容。 - Warren P
它是DB数据,只是它没有存储在这个特定的表中。我也知道绑定,但我正在使用D2010,我没有时间开始使用自定义库..(stackoverflow.com/questions/7882599/...) - pragmatic_programmer


答案:


您是否尝试过使用InternalCalc字段?您的数据感知控件将允许您编辑InternalCalc字段的值,并将值存储在数据集中。

如果您在设计时在数据集(TClientDataSet,TQuery等)中创建InternalCalc字段,那么它几乎就是您所要求的。


10
2017-11-03 17:18



我只想写同样的答案。 - Uwe Raabe
这看起来像是原生的vcl方式..我测试了它并且在设计时工作得很好..不幸的是我在运行时创建了所有数据集而没有fielddef定义..(基本上我设置了SelectSQL.Text,并调用Open,所以字段从SQL字段列表中创建)。我试图在DataSet的AfterOpen事件中添加该字段,但它引发了一个例外“无法在打开的数据集上执行此操作”..解决此问题的任何解决方法?谢谢 - pragmatic_programmer
这不适用于auto-create-field选项。它与普通的calc字段相同。您必须在打开数据集之前使用静态字段或在运行时创建所有字段。可以打开数据集,保存字段defs,关闭它,创建字段加上calc字段并再次打开它。这需要一些棘手的实现。 - Uwe Raabe


您可以在Interbase / Firebird数据库中创建可更新视图(在插入/更新/删除触发器之前)。这看起来像是客户端的“虚拟表”(视图声明的select语句也可以包含“虚拟字段”),完全取决于您如何实现触发器。


3
2017-11-03 16:17



对于其他情况我相信的一个很好的技巧..在这种情况下1)逻辑进入触发器2)我必须发布到虚拟表(可更新视图)以获取执行的触发器并获取其他字段更新(这最后一件事在我的情况下是不可行的)..我是对的? - pragmatic_programmer
是的,客户端必须发布到视图并重新加载视图以获取更新的值。 - Ondrej Kelle


您可以将Calcfield写为可写:

type
  TCalcStringField = class(TWideStringField)
    function GetCanModify: Boolean; override;
  end;


function TCalcStringField.GetCanModify: Boolean;
begin
  // Makes Calcfield editable
//if FieldNo > 0 then
    if DataSet.State <> dsSetKey then
      Result := not ReadOnly and DataSet.CanModify
    else
      Result := IsIndexField
//else
//  Result := False;
end;

将Calculated设置为true,然后在此Field的OnSetText中,您可以将Text写入任何其他位置

procedure TformXX.XXOnSetText(Sender: TField; const Text: string);
begin
   ...
end;

2
2017-11-03 17:22