0

I have a class which should contain datafields like TIntegerField, TFloatField, ... In an Init-Function I want to open a dataset to get the right datarecord from DB and put the values to the fields in the classinstance. Because I don't want to write down all the fields of the class I want do this dynamicly with rtti. I wonder how I can create an instance e.g. of a TFLoatfield and copy the FloatField from dataset to classfield. My function finds the floatfiled but I cannot create the Instance and copy the value.

var
  rttiContext: TRttiContext;
  rttiType: TRttiType;
  attribute: TCustomAttribute;
  rttiField: TRttiField;
begin
  myQuery.Close;
  myQuery.SQL.Clear;
  myQuery.SQL.Add('SELECT * FROM prices');
  myQuery.SQL.Add('WHERE ID=' + IntToStr(FID));
  myQuery.Open();
  try
    rttiContext := TRttiContext.Create;
    try
      rttiType := rttiContext.GetType(TPrice);
      for rttiField in rttiType.GetFields do
      begin
        if rttiField.FieldType.ToString = 'TFloatField' then
        begin
          // create Instance of Floatfield does not work!
          if not assigned(TFloatField(rttiType.GetField(rttiField.Name))) then
            TFloatField(rttiType.GetField(rttiField.Name)).Create(nil);
          // Copy Floatfield from dataset to classfield does not work!
          TFloatField(rttiType.GetField(rttiField.Name)).Value := tmpQuery.FieldByName(rttiField.Name).Value;
        end;
      end;
    finally
      rttiContext.Free;
    end
  finally
    myQuery.Close;
  end;
end; 
5
  • Ok, but what is your question? And why don't you just do what everyone normally does, i.e. either create persistent TFields, or just let the dataset create them dynamically when it is opened? Commented Apr 6, 2017 at 9:09
  • what do you mean with persistent TFields? I want to map tables in classes. Commented Apr 6, 2017 at 9:20
  • Right-click the dataset in the IDE, select Fields Editor and then use the menu to create the fields from the dataset. Fields created that way "persist" because they are created on the form/datamodule. Commented Apr 6, 2017 at 9:24
  • Ahh ok the normal way :) but I want for each table a class. So I can open it with mytable := TCostumer.create(1) to get the record with ID=1. Commented Apr 6, 2017 at 9:48
  • Then I think you'd better read my answer. There's certainly nothing stopping you creating a customised dataset, but you need to understand what you can and can't do, in terms of creating and using TFields. Commented Apr 6, 2017 at 9:56

1 Answer 1

0

Your comment

Copy Floatfield from dataset to classfield does not work!

is correct, TFields only work when they are associated with a TDataSet; they cannot work in isolation from one because they use the record buffers set up by the dataset to hold the data they operate on.

create Instance of Floatfield does not work!

Wrong. You can create an instance of TFloatField by whatever method you like, e.g.

var FloatField : TFloatField;

  FloatField := TFloatField.Create(Self);  //  self being e.g. TForm1 or DataModule1
  FloatField.FieldName := 'AFloatField';
  FloatField.FieldKind := fkData;
FloatField.DataSet := myQuery;
  [etc]

but I think the point that you have missed is that you can only do this successfully before the dataset is opened. Once the dataset is open it is too late because in the absence of persistent fields, the dataset will create dynamically a set of default fields which only live as long as the dataset is open.

"Persistent" Fields are so called because they are stored in the DFM of the form or DataModule in which they are created using the Fields Editor you can access using the context menu of the dataset in the IDE.

Btw, many people have using Attribute annotations for classes to create customised datasets. One good article on it is here:

http://francois-piette.blogspot.co.uk/2013/01/using-custom-attribute-for-data.html

You might also want to take a look at the Spring4D library, which might save you a lot of work. See e.g. https://spring4d.4delphi.com/docs/develop/Html/index.htm?Spring.Persistence.Core.Base.TDriverResultSetAdapter(T).DataSet.htm as a way into it.

Sign up to request clarification or add additional context in comments.

10 Comments

>>"TFields only work when they are associated with a TDataSet" OK then I need own classes for my Integerfields, Floatfields, ... in my mappingclasses? But how can I create these objects in my Init-function with rtti?
What are you asking by quoting that?
thx for the Links. We already use thes classes to read from our DB but now we want to write an I have Problems with values that are NULL on DB. In my classes I have Integer, TDateTime, ... when I read from DB they get the Value 0 when they are NULL on DB. When I want to write them back I don't know if the ware NULL before or 0.
That's a completely different point than what you asked in your q. The .AsInteger, AsFloat, etc getters for TField values return 0 when the field in the DB is actually NULL, but you can test for that in code using the TField.IsNull function.
No, I mean at the moment I have no datafields in my classes. I use normal types like integer, double, ... This was ok as long I was only reading with my classes. Now I want to write to my Database and when eg my Integer value is 0 I don't know whether my value is 0 or NULL.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.