Projected Entities do not fetch subprops

As you describe here we could

Limiting the selected properties

I gave this a try by doing this:

    hChildren := hManager.Find<TChild>
      .Select(TProjections.ProjectionList
        .Add(Linq['Caption'])
        .Add(Linq['Parent.Caption'])
      )
      .List;

Using your OnSqlExecuting and logging SQL I got this:

SELECT A.ID AS A_ID, A.CAPTION AS A_CAPTION
FROM CHILD A
  LEFT JOIN PARENT B ON (B.ID = A.PARENT_ID)

That's my model:

type
  TEntityId = Integer;

  [AbstractEntity, Automapping]
  TBaseEntity = class(TObject)
  private
    FId: TEntityId;
    FCaption: string;
  public
    property Id: Integer read FId write FId;
    property Caption: string read FCaption write FCaption;
  end;

  [Entity, Automapping]
  TParent = class(TBaseEntity)
  end;

  [Entity, Automapping]
  TChild = class(TBaseEntity)
  private
    FParent: Proxy<TParent>;

    function GetParent: TParent; // => Result := FParent.Value
    procedure SetParent(const Value: TParent); // => FParent.Value := Value...
  public
    property Parent: TParent read GetParent write SetParent;
  end;

Afterwards I saw, that you are using FetchEager in your docs, so I did this:

    hChildren := hManager.Find<TChild>
      .Select(TProjections.ProjectionList
        .Add(Linq['Caption'])
        .Add(Linq['Parent.Caption'])
      )
      .FetchEager('Parent')
      .List;

but I got the same SQL...

SELECT A.ID AS A_ID, A.CAPTION AS A_CAPTION
FROM CHILD A
  LEFT JOIN PARENT B ON (B.ID = A.PARENT_ID)

In both cases hChild.Parent is nil, so that I could not access my fetched subproperty...

Did you try a CreateAlias for Parent before adding to the ProjectionList ?

I did not, but now I did and it also does not work...

    Result := aManager.Find<TChild>
      .CreateAlias('Parent', 'prnt')
      .Select(TProjections.ProjectionList
        .Add(Linq['Caption'])
        .Add(Linq['prnt.Caption'])
      )
      .List;

I also put result into an AureliusDataset with following Fields:

- Caption
- prntCaption

while using Aliased Linq:

    Result := aManager.Find<TChild>
      .CreateAlias('Parent', 'prnt')
      .Select(TProjections.ProjectionList
        .Add(Linq['Caption'])
        .Add(Linq['prnt.Caption'].As_('prntCaption'))
      )

prntCaption stays empty...

ohhh .. now I see...
Use .ListValues instead of .List

Yeah, this would work, BUT I need TList<TChild>, not a criteria-Result list.

and as described in documents, .List should also work...

With the projection you'd get only child Caption and parent Caption at the same "row level". It does not work on a TCHild structure returned from .List.

If you want a TList, FetchEager on Parent should work. Maybe there's another mapping issue to solve.

Try declaring FParent without Proxy. This will force eager loading.
Or you could try the complete association attributes.

You have to explicitly tell Aurelius that you want the association to be included in select. Do this:

    hChildren := hManager.Find<TChild>
      .Select(TProjections.ProjectionList
        .Add(Linq['Caption'])
        .Add(Linq['Parent'])
        .Add(Linq['Parent.Caption'])
      )
      .List;

Ok, but why does your example not work?

  Estimates := Manager.Find<TEstimate>
    .Select(TProjections.ProjectionList
      .Add(Linq['EstimateNo'])
      .Add(Linq['Customer'])
      .Add(Linq['Customer.Name'])
      .Add(Linq['Customer.Sex'])
      .Add(Linq['Customer.Country'])
      .Add(Linq['Customer.Country.Id'])
    )
    .FetchEager('Customer')
    .FetchEager('Customer.Country')
    .List

should FetchEager not do the same?

ok, finally I saw this in your example...
It's a little bit confusing combined with FetchEager

1 Like

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