Page 1 of 1

AV referencing persistent field object by name

Posted: Wed 03 Oct 2012 06:14
by francoff
Hi.
I am making some experiments with Virtual Table Free (last) and D 2009.

I have found that referencing a field directly by field.name (e.g. Table1Field1.AsString) raises an AV Exception, while using usual FieldByName or FieldValues works properly.
Directly referencing persistent fields not only is extremely faster (which matters only in loops on large numbers of records), but also allows to check correct naming at compile time.

I think this is a bug, so I have set up a small example to reproduce it.
Let me know how I can post/send to You.
Regards.

Re: AV referencing persistent field object by name

Posted: Wed 03 Oct 2012 13:46
by AlexP
hello,

We couldn't reproduce the AV when working with persistent fields of VirtualTable, please send your sample demonstrating the problem to alexp*devart*com

Re: AV referencing persistent field object by name

Posted: Thu 04 Oct 2012 06:52
by francoff
Hi.
I think that the AV Exception might be simply due to the fact that no persistent TFields are present at runtime so you cannot reference them directly by name. At runtime, may be, there are only dynamic TField objects, and persistent fields created at designtime are no longer available.
This is only an assumption, and, if it is correct, it may be by design (which should be made clear) or due to a flaw. In any case if there is no other way to create persistent fields, this is a real disadvantage.

Re: AV referencing persistent field object by name

Posted: Fri 05 Oct 2012 09:12
by AlexP
hello,

When using the VirtualTable.Assign method, all the existing data and fields in the table are cleared. Therefore, after data loading, the fields created earlier become nil.
There are two way to solve this problem:

1) Relate the fields in the following way:

Code: Select all

Table1.Open;
vt1.Assign(Table1);
vt1DATA := TDateField.Create(nil);
vt1DATA.FieldName := 'DATA';
vt1DATA.DataSet := vt1;
vt1NOTE := TStringField.Create(nil);
vt1NOTE.FieldName := 'NOTE';
vt1NOTE.DataSet := vt1;
vt1.Open;
Table1.Close;
2) Or, if the structures of the table and VirtualTable are similar, use the TCRBatchMove component for data transfer between datasets

Re: AV referencing persistent field object by name

Posted: Sat 06 Oct 2012 05:49
by francoff
Hi Alex.
Thank you very much for helping.

After some research, I ended up with a piece of code that seems to work and lends itself to be transformed in a generic routine.
It is assumed that persistent fields were created for the base table (and also for Virtual Table otherwise direct references to field objects would give a compile error):

...
var
i: integer;
Field, NewField: TField;
begin

vt1.DisableControls;
try
Table1.Open;
try
vt1.Assign(Table1);
finally
Table1.Close;
end;
for i := 0 to Table1.FieldCount - 1 do
begin
Field := Table1.Fields;
NewField := vt1.FieldDefs.CreateField(Self);
//CreateField(vt1) somehow gives AV again
NewField.Visible := Field.Visible;
NewField.Name := 'vt1' + NewField.FieldName;//<- this is the key point to solve AV issue.
NewField.DisplayLabel := Field.DisplayLabel;
NewField.DisplayWidth := Field.DisplayWidth;
NewField.EditMask := Field.EditMask;
if IsPublishedProp(Field, 'currency') then
SetPropValue(NewField, 'currency', GetPropValue(Field, 'currency'));
// may be here it can be improved adding more published props.
end;
finally
vt1.EnableControls;
end;
...