Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to delay projection of the $select clause until after enumeration? #1405

Open
mfaulcon opened this issue Feb 4, 2025 · 2 comments

Comments

@mfaulcon
Copy link

mfaulcon commented Feb 4, 2025

For my use case, my data source is an IQueryable, where T must have a custom attribute applid. The net effect of this is that anonymous projections are not supported.

I have tested it as a source for OData, and as long as I do not have a $select clause, everything seems to work as work as expected; as soon as I add one, I get an exception. Is there a way for me to delay projection to the anonymous type until after the IQueryable has been queried and enumerated?

@gathogojr
Copy link
Contributor

gathogojr commented Feb 4, 2025

@mfaulcon You can try the following:

  • You can call ToList or ToListAsync from the controller action and change the return type for the controller action to IEnumerable. This cause the IQueryable to be executed before applying any query actions (including $select, $filter, $expand, etc). The query options will be applied in memory - not deferred to the backend/data source. This could lead to higher memory consumption and/or performance degradation.
  • You can customize the SelectExpandBinder such that you're able to apply the missing property before the query options are applied. You'd then need to inject the custom SelectExpandBinder as a service.
  • You can also call ApplyTo after modifying the SelectExpand property of the ODataQueryOptions object to add the missing property. This would require you to change the signature the controller action to accept an ODataQueryOptions<T>, i.e., remove the EnableQuery attribute:
    public ActionResult<IQueryable> Get(ODataQueryOptions<T> options)
    {
        // options.SelectExpand... // Modify ODataQueryOptions object here
        // options.ApplyTo(...);
    }

Kindly let us know if this helps. If it doesn't, please share a repro that we can use to investigate.

@julealgon
Copy link
Contributor

Another option would be to create an alternative version of the [EnableQuery] attribute that calls ODataQueryOptions.ApplyTo twice: once with "all operators but the $select one", then another time with just the $select after materializing the IQueryable to an IEnumerable.

It might be possible even by just overriding the 2 ApplyQuery methods and just putting the logic there:

We once did something like this to perform an extra custom projection on top of the one specified on $select by passing a final "projection DTO model" as a parameter to a modified version of [EnableQuery]. What you need seems a bit more straightforward than that so it should definitely work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants