SubCriteria with TCustomCriterion

I have a subquery (SubCriteria) working in the following form:

  Cars := ObjManager.Find<TCar>.SubCriteria('Tags')
    .Where(Linq['Text'].Upper._In(SelectedTagsArray))
    .RemovingDuplicatedEntities.List<TCar>;

I want to use TCustomCriterion, but only if my "SelectedTagsArray" has at least one item. I'm having difficulty figuring out how to build a Filter/TCustomCriterion with a SubCriteria. For example:

var
  Cars: TObjectList<TCar>;
  Criteria: TCriteria<TCar>;
  Filter: TCustomCriterion;
  SelectedTagsArray: TArray<Variant>; // String

...

 Criteria := ObjManager.Find<TCar>;

 SelectedTagsArray := GetSelectedTagsArray;
 if Length(SelectedTagsArray) > 0 then
 begin
   Filter:=SubCriteria('Tags').Where(Linq['Text'].Upper._In(SelectedTagsArray));  //<<-- This is the line of code giving me challenges
   Criteria.Add(Filter);
 end;

 Cars := Criteria.RemovingDuplicatedEntities.List;

Any ideas for how to build a SubCriteria filter?

Wouldn't it be easier if you just not use SubCriteria, but aliases instead? It's always the recommended way to build queries, because it's simpler to understand and build:

  .Where(Linq['Tags.Text'].Upper._In(SelectedTagsArray))

Thank you, Wagner. Yes, the Where without SubCriteria is simpler to build and to understand. How do I assign this to the TCustomCriterion Filter variable?

By trial and error, I was able to get this to work (switched back to SubCriteria):

Criteria := ObjManager.Find<TCar>;

SelectedTagsArray := GetSelectedTagsArray;

if Length(SelectedTagsArray) > 0 then
  Criteria.SubCriteria('Tags').Where(Linq['Text'].Upper._In(SelectedTagsArray));

Cars := Criteria.RemovingDuplicatedEntities.List;

If I do it this way, I get an error:

Criteria := ObjManager.Find<TCar>;

SelectedTagsArray := GetSelectedTagsArray;

if Length(SelectedTagsArray) > 0 then
  Criteria.Where(Linq['Tags.Text'].Upper._In(SelectedTagsArray));

Cars := Criteria.RemovingDuplicatedEntities.List;

The error is: "Could not retrieve aliased column name in criteria (D:\Dev...\Aurelius.Commands.Selector.pas, line 1149)'. It seems it cannot resolve 'Tags.Text', perhaps because Tags is defined as TList<TTag>?

That's fine.

Are you using latest Aurelius version? Then automatic aliasing should work. If not, you can simply create the alias manually:

if Length(SelectedTagsArray) > 0 then
begin
  Criteria.CreateAlias('Tags', 'Tags');
  Criteria.Where(Linq['Tags.Text'].Upper._In(SelectedTagsArray));
end;

Thanks again, Wagner. I'm using Aurelius 5.14. Adding CreateAlias with Criteria.Where (as you provided) works, but without CreateAlias, the same error message persists.

I'm glad you solved your problem. But auto alias should be working fine. If you want to send us a project reproducing the issue (which we can compile and run at our side), we can try to check what's going on.

AureliusAlias.zip (27.9 KB)

Attached is a Delphi project that reproduces this. To produce the error, click on the "Electric Cars Only" button when running the program.

Thank you very much. The project indicated that the automatic alias was not working correctly when used with predefined functions, which was the case of the Upper function you used, for example. That's why it was not working.

We fixed this internally and next release will include the fix. In the meanwhile, you can simply continue using the workaround, which is explicitly create the alias using CreateAlias function.

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