gpt4 book ai didi

arrays - Delphi 中的 FDQuery (SQL) 结果到记录数组

转载 作者:行者123 更新时间:2023-12-03 15:23:22 24 4
gpt4 key购买 nike

有没有办法将 FDQuery 结果直接复制到记录数组?所以这是声明的类型:

type
TPerson = record
id: integer;
name: string;
surname: string;
end;

type
TPersonList = array of TPerson;

我有 SQLite DB,其中包含 id、namesurname 列。通常我应该像这样向该数组添加值:

var Persons: TPersonList;
begin
Persons[0].id := FDQuery1.FieldByName('id').AsInteger;
....
....
....
end;

但是有没有更好/更紧凑的方法来做到这一点?有些功能如下:

while not FDQuery.eof do begin
...
Persons[i] := FDQuery1[i];
...
end;

也许直接还是在循环中?或者我应该创建一些函数来做到这一点?因为我有很多列,以及许多不同的记录类型,它们具有不同的结构,但具有与数据库一样的精确结构。

最佳答案

没有简单的方法可以直接执行此操作,但是可以使用一些技术来提高源代码和运行时性能的效率。一种方法可能是创建一个简单的帮助器来初始化给定数据集中适当类型的新值。

您可以为此使用记录方法,但这将使使用缓存的字段引用变得不太优雅,因此我建议使用单独的专用初始化程序类。这可以使用缓存的字段引用来提高效率:

type
TPersonFDInitialiser = class
private
fldID: TIntegerField;
fldName: TStringField;
fldSurname: TStringField;
function get_NewValue: TPerson;
public
constructor Create(const aSource: TDataset);
property NewValue: TPerson read get_NewValue;
end;

在构造函数中缓存字段引用可以避免每次检索每条记录的值时都必须按名称查找它们。对字段数据类型使用适当的类可以直接访问每个字段值,而无需进行任何转换:

constructor TPersonFDInitialiser.Create(const aSource: TDataset);
begin
inherited;

fldID := aSource.FieldByName('id') as TIntegerField;
fldName := aSource.FieldByName('name') as TStringField;
fldSurname := aSource.FieldByName('surname') as TStringField;
end;


function TPersonFDInitialiser.get_NewValue: TPerson;
begin
result.ID := fldID.Value;
result.Name := fldName.Value;
result.Surname := fldSurname.Value;
end;

正如您所看到的,这并不是一个巨大的工作量(比显式初始化 1 个记录值所需的工作量多一点),但使迭代使用更加优雅且编写起来更快,看起来有点像这样:

recno := 0;
init := TPersonFDInitialiser.Create(qryPersons);
try
while NOT qryPersons.EOF do
begin
persons[recno] := init.NewValue;

qryPersons.Next;
Inc(recno);
end;

finally
init.Free;
end;

其中 qryPersons 是一些返回人员行的 TFDQuery,而 persons 是您的 TPerson 记录数组(大小/当然要适本地管理)

通过使用TDataset基类(TFDQuery最终派生自该基类),您可以在需要初始化TPerson的任何地方使用此初始化程序类> 来自 TDataset 后代,无论是 TFDQuery 还是 TClientDataset 或其他什么(只要该数据集中的字段命名一致,如所写,但如果需要的话,初始化程序可以在这方面变得更加灵活。这作为练习)。

走得更远

可以根据您的需要进行许多增强功能来提高此类初始化程序类的实用性,例如:

// To initialise a one-off, new TPerson value from a data set use a 
// class function which will internally create an initialiser, obtain
// a new TPerson then destroy the initialiser for you:
//
// Note that this will need to be overloaded if it has the same name as
// the instance method (which must also then be overloaded):

class function TPersonFDInitialiser.NewValue(const aSource: TDataset): TPerson; overload;


// Implement a procedure which will initialise an existing TPerson value
// (by reference) with values from the current record.
//
// Again, a class procedure overload could be provided for one-off use
// taking care of creating and freeing the required initialiser:

class procedure TPersonFDInitialiser.SetPerson(const aSource: TDataset; var aPerson: TPerson); overload;
procedure TPersonFDInitialiser.SetPerson(var aPerson: TPerson); overload;

注意:这些 SetPerson 方法可以通过以下方式实现:get_NewValue 实际上调用该方法,这样整个实现中只有一个方法 实际上执行任何值设置。这将消除初始化代码的重复,提高初始化类的可靠性和可维护性:

function TPersonFDInitialiser.get_NewValue: TPerson;
begin
SetPerson(result);
end;


procedure TPersonFDInitialiser.SetPerson(var aPerson: TPerson);
begin
aPerson.ID := fldID.Value;
aPerson.Name := fldName.Value;
aPerson.Surname := fldSurname.Value;
end;

关于arrays - Delphi 中的 FDQuery (SQL) 结果到记录数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27156368/

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