Admiral Noisey Bottom
Admiral Noisey Bottom

Reputation: 122

Storing Component Name as a String for later use

On my form I have a number of TMyQuery Components. Their names identify which MySQL Tables they work with. For example, COMPONENTSTABLE works with the COMPONENTS TABLE, etc.

There are about 30 tables, but that might change in the future.

I also use a basic String List to read field names from a Table called TIMESTAMPS. This table is updated via triggers when an UPDATE, INSERT, or DELETE occurs. Each field within the TIMESTAMPS Table refers to which Table was modified. There's only one record in the table! Based on the field values I can see which table changed so I can refresh it rather than refreshing all of them.

I don't want to do this;

If fieldbyname['COMPONENTSTABLE'] <> CurrentTimeStamp
 then ComponentsTable.Refresh;

If fieldbyname['ORDERSTABLE'] <> CurrentTimeStamp
 then OrdersTable.Refresh;

{ and so on forever }

What I want to do is;

Right now I have a String List with "Names / Values". Each "Name" is the Fieldname within the Table and "Value" is the TIMESTAMP provided by MySQL Triggers.

I've got the following;

For Idx := 0 to MyStringList.Count -1 do
  Begin

    If MyStringlist.ValueFromIndex[Idx] <> SomethingElse then 
     Begin
        with (MyStringList.Names[Idx] as tMyQuery).Refresh;
     End;

  End;

I've got the String List functioning, the Names, the Values etc are all correct.

My question is this;

Is there a way I can use a String ("Names" column in the list) to refer to an Object if that Object exists?

I already have a function I use to refresh individual tables by passing an Object to it, but that's an Object and easy to work with. I'd like to pass the "Object" based on it's name retrieved from a String.

I hope this makes sense and you can follow what I'm after.

Upvotes: 0

Views: 2100

Answers (2)

Admiral Noisey Bottom
Admiral Noisey Bottom

Reputation: 122

While the first part of the accepted Answer from @pepak isn't what I was looking for ( I've used similar code in the app previously and found it slow ), the second part of the Answer pointed my in the right direction.

My (thanks to Pepak) eventual solution was;

Function RefreshQueryByName(Const Name: String): Boolean;
   Var
      Obj: TComponent;
   Begin
      Result := False;
      Obj := Self.FindComponent(Name);
      If Obj <> nil Then
         If Obj Is TMyQuery Then
            With Obj As TMyQuery Do
               If Active Then
               Begin
                  Refresh;
                  Result := True;
               End;
   End;

Which I use by by passing a String I get from a Field Value that identifies which table I want to refresh.

Now, my Database App automatically refreshes a table changed by other users. It will now refresh any of the 30 tables of they are modified by another user without refreshing all tables.

Thanks for your help Pepak, I've accepted your answer and hope it is useful to others.

Upvotes: 0

pepak
pepak

Reputation: 742

I am not sure what your question actually is. In the first part of the answer I assume that you don't really care about names of the objects but rather want some automated way of getting all the tables available refer to a field in another table. Below that, I answer your question about referring to an object if you know its name.

Automated way of handling all tables

It depends on what class your objects are.

From your description, I assume your TMyQuery are TComponent descendants owned by the form. Then the solution is very simple, as each TComponent has both a public Name and a list of owned components Components. You can then use something like this:

var
  i: integer;
  MyQuery: TMyQuery;
begin
  for i := 0 to Pred(MyForm.ComponentCount) do
    if MyForm.Components[i] <> TimeStampsTable then
      if MyForm.Components[i] is TMyQuery then
      begin
        MyQuery := TMyQuery(MyForm.Components[i]);
        if TimeStampsTable.FieldByName(MyQuery.Name).AsDateTime >= LastAccess then ...
      end;
end;

Note that you may want to add extra checks, e.g. to make sure that MyQuery.Name is not empty or that it exists as a field in TimeStampsTable.

If your objects are only TObjects, then there is no "standard" name property and no standard registration of these objects. Name can be handled, apparently your component already has one so it's just a question of a proper type coercion, but object registration is a different matter. You may have to create some kind of a global list for all your created TMyQuery instances.

Getting an object instance based on that object's name

function TMyForm.GetQueryByName(const Name: string): TMyQuery;
var
  Obj: TObject;
begin
  Result := nil;
  Obj := Self.FindComponent(Name);
  if Obj <> nil then
    if Obj is TMyQuery then
      Result := TMyQuery(Obj);
end;

Or you could simply loop over all Components and use your own Name matching.

Upvotes: 2

Related Questions