gpt4 book ai didi

windows - 我需要避免尝试更新连接到 TSQLQuery 的 Delphi TClientDataset 中的非物理字段

转载 作者:可可西里 更新时间:2023-11-01 12:49:50 27 4
gpt4 key购买 nike

Precis:我的代码试图更新 Delphi XE TClientDataset 中的非物理字段,(连接到 TSQLQuery 及其 SQL作为运行时 Open 命令的结果创建的属性集)。

我有一个 TClientDataset 连接到一个 TDatasetProvider 连接到一个 TSQLQuery 连接到一个 TSQLConnection。这些对象中的前 3 个被封装在我在多个项目的许多地方使用的库中的几个类中。这些类在运行时创建这 3 个对象并消除大量重复代码,这是必要的,因为我有很多很多这样的三元组。

通常我会通过在 TSQLQuerySQL 属性中指定一些 SQL 并调用 从数据库加载 TClientDatasetTClientDataSet 上打开TClientDataset 中的Fields 是通过调用Open 创建的,即。它们在 Open 之前不存在。

TClientDataset 中生成的三个字段是非物理字段的情况下,我遇到了一个问题;也就是说,SQL 进行计算以生成它们。不幸的是,在 TClientDataset 中,这 3 个字段的创建方式与物理字段没有任何不同;他们的 FieldKindfkData(理想情况下是 fkInternalCalc),Calculated 属性是 False(理想情况下应该是 True)并且它们的 ProviderFlags 包括 pfInUpdate(理想情况下它不应该)。毫不奇怪,当需要在 TClientDataset 上执行 ApplyUpdates 时,会抛出异常...

Project XXX.exe raised exception class TDBXError with message
SQL State: 42S22, SQL Error Code: 207 Invalid column name 'Received'.
SQL State: 42S22, SQL Error Code: 207 Invalid column name 'Issued'.
SQL State: 42S22, SQL Error Code: 207 Invalid column name 'DisplayTime'.

我可以通过在 TDatasetProviderOnUpdateData 事件处理程序中清除这些字段的 pfInUpdate 标志来避免此错误。但是,此解决方案要求位于上述泛型类中的此函数知道特定字段名称,从而破坏了代码的通用性。

我正在寻找一种通用方法,将这些字段的计算性质发送给事件处理函数。

我无法在 之后更改它们的 FieldKindCalculated 属性(分别为 fkInternalCalcTrue) >Open 调用,因为这会生成 WorkCDS: Cannot perform this operation on an open dataset 异常消息。而且,我无法在 Open 调用之前更改这些属性,因为 Fields 尚不存在。

我可以在 Open 之后从这些 FieldProviderFlags 属性中删除 pfInUpdate 标志,但这不会传递到到达 OnUpdateData 事件处理程序的“Delta”TClientDatset。我还尝试设置字段的 FieldDefs.InternalCalcField 属性;同样,这不会传递到 Delta 数据集。

所以,我尝试过的所有信号想法都没有奏效。如果有任何新想法或替代方法,我将不胜感激。

我遇到的所有互联网搜索结果 - 包括 Cary Jensen 的优秀文章 - 处理不适用于我的情况的设计时或非 SQL 生成的设置。

最佳答案

您可以在您的类中创建一种机制,为您希望在更新过程中忽略的各个字段预配置 ProviderFlags。

根据对您问题的评论,我建议您在类中创建一个新方法来打开内部 ClientDataSet,所有魔法都将在该方法中发生。

首先,一个简单的机制是包含一个新的 TStringList 属性,它列出了您要忽略的所有字段,您将按名称匹配这些字段。随意采用这个或创建一个新的更好的机制,重要的是您能够确定要以这种方式配置哪些字段。

type
TMyClass = class
// all your current class here
private
FUpdateIgnoredFields: TStringList;
public
property UpdateIgnoredFields: TStringList read FUpdateIgnoredFields write SetUpdateIgnoredFields;
//don't forget to create this in your constructor, free it in the destructor
//and Assign any new value in the SetUpdateIgnoreFields method, as usual.
procedure OpenInnerCDS; //the magic goes here
end;

procedure TMyClass.OpenInnerCDS;
var
FieldName: string;
AFieldToIgnore: TField;
begin
//opens the inner cds, but before that, configures the update-ignored
//fields in the underlying dataset
//Let's call it InnerBaseDataSet;
FInnerBaseDataSet.Open; //this opens the DataSet and creates all the fields for it.
try
for FieldName in FUpdateIgnoredFields do
begin
AFieldToIgnore := FInnerBaseDataSet.FindField(FieldName);
if Assigned(AFieldToIgnore) then
AFieldToIgnore.ProviderFlags := AFieldToIgnore.ProviderFlags - [pfInUpdate, pfInWhere];
end;
//now, let's open the ClientDataSet;
FInnerClientDataSet.Open;
finally
//I suggest no matter what happens, always close the inner data set
//but it depends on how the CDS->Provider->DataSet interaction is configured
FInnerBaseDataSet.Close;
end;
end;

//the way you use this is to replace the current ClientDataSetOpen with something like:

var
MyInsance: TMyClass;
begin
MyInstance := TMyInstance.Create(); //params
try
//configuration code here
//MyInstance.InnerCDS.Open; <-- not directly now
MyInstance.UpdateIgnoreFields.Add('CALCULATED_SALARY');
MyInstance.OpenInnerCDS;
//use the CDS here.
MyInstance.InnerCDS.ApplyUpdates(-1); //safely apply updates now.
finally
MyInstance.Free;
end;
end;

把它当作一个想法。

我在这里写了所有的代码,也许语法有误,但它展示了整个思路。

关于windows - 我需要避免尝试更新连接到 TSQLQuery 的 Delphi TClientDataset 中的非物理字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13505612/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com