How to Reuse TLinqExpression

Hello,

i've got problems with TLinqExpressions.
I'm creating a Frame with the follwing Constructor:

constructor TfrReparaturlist.Create(AOwner: TComponent;Guid:TGuid;From:String;AFilter:TLinqExpression);
var
  LocalFilter: TLinqExpression;
begin
  inherited Create(AOwner);
  ParentGuid:=Guid;
  Parentform:=From;
  Sortfield:='Eingangsdatum';
  SortOrderAsc:=true;
  Filter := AFilter;
  LoadReparatur;
end;
procedure TfrReparaturlist.LoadReparatur;
begin
  aGrid.Close;
  Entities:= dmmain.MainXDClient.List<TReparatur>(CreateQuery.From(TReparatur)
      .Filter(Filter)
      .OrderBy(Sortfield,sortorderasc)
      .QueryString);
  aGrid.SetSourceList(Entities,true);
  aGrid.Open;
  Summe(Entities);
  TGridConfigurator.ReparaturGrid(dagReparaturen,ParentForm);
end;

The Variable Filter is definied as TLinqExpression.

If i create the frame with a given TLinqExpression it works, fine.
But if i recall the procedure LoadReparatur i always get a "Access Violation" Error.
If i delete the .Filter(Filter) part from the Query, i get no error.

I already tried to use TCustomCriteria instead of TLinqExpression which leads to the same error.
Looking through the forum it's mentioned, that TLinqExpressions are References and no fixed Variables so i guess that's where the problem comes from.
How can i fix this?
Is there a way to safe the TLinqExpression so that i can reuse the Filter without recreating the filter beforehand so that i can use sorting for example?

Kind regards,

Could you check or share your code between the first time you call Create and pass AFilter , and the time you said you "recall" LoadReparatur ? Also check or share where you declare your initial TLinqExpression.

Are these calls at the same level? Or at least is the original TLinqExpression record variable visible to both calls as if it was public? I'm afraid this record variable could had been already freed by the time you run the second call.

1 Like

Correct, one a TCustomExpression is added to the criteria, it's destroyed together with it. So you can't reuse it.

One thing you can do is use Criteria.Clone method to duplicate the criteria. And (or) set Criteria.AutoDestroy to False and destroy the criteria yourself when TfrReparaturList is destroyed.

1 Like

Thank you very much for your help.

@Julio_R_Ferrari
Yes, the calls are on the same level.
When i create the frame, "loadReparaturen" gets called with the Filter provided to the Frame.
The initial call works but when i want to recall "loadReparaturen" with changed Sort-Parameters, it wont.
The Filter is (now) saved as TCustomCriterion.

@wlandgraf
The Clone method did the trick.

procedure TfrReparaturlist.LoadReparatur;
var
  aFilter:TCustomCriterion;
begin
  aGrid.Close;
  AFilter:=Filter.Clone;
  Entities:= dmmain.MainXDClient.List<TReparatur>(CreateQuery.From(TReparatur)
      .Filter(AFilter)
      .OrderBy(Sortfield,sortorderasc)
      .QueryString);
  aGrid.SetSourceList(Entities,true);
  aGrid.Open;
  Summe(Entities);
  TGridConfigurator.ReparaturGrid(dagReparaturen,ParentForm);
end;

Thanks to both of you for the fast reply!

Kind regards

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.