ChilliCream / ChilliCream/graphql-platform

Fallback resolver outside Projection context

Open
#5,277 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

🌶️ hot chocolate Area: Data Area: Projections
Dominant language
C#
Stars
5.8k
Forks
810
Avg merge
15h 39m
Merged PRs (30d)
98

Description

Is your feature request related to a problem?

Sample code:

class Brand
{
    public int Id { get; set; }
    public string? Name { get; set; }
} 

class Car
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public int BrandId { get; set; }

    // Reachable through IQueryable
    public Brand? Brand { get; set; }
}

class Queries
{
    [UseProjection]
    public IQueryable<Car> GetCars(DbContext dbContext)
        => dbContext.Set<Car>();

    public Task<Car> GetCarAsync(int id, [DataLoader] CarLoader loader)
        => loader.LoadAsync(id);
}

Query:

query {
   cars {
      brand {
          name
      }
   }
   car(id: 5) {
      brand {
          name
      }
   }
}

In node cars we find that each car has a brand. In node car we find that car has null brand. We cant fix that by defining a resolver.

public class CarExtensions
{
    public Task<Brand> GetBrandAsync([Parent] Car car, [DataLoader] BrandLoader loader)
        => loader.LoadAsync(car.BranchId);
}

Now if we re-run the query both cars and car return a brand. However, brand in cars is no longer projected and instead is loaded by the resolver. If Brand cannot be loaded outisde projection context, object type Car is usable solely in Projection context. As a result I might want to create separate object type CarToBeUsedOutisdeProjection which will use data loaders to load data. Or I can rename resolver brand to brandForUseOutsideProjection. However, this forces client to distinguish between projection and non projection context (basically shcema get's doubled as parallel structure has to be build for non projection context).

This issue can be genrally solved by using projection in car. But as stated above I cannt use car outside a node tree that begins with projection.

class SomeCaculatedStuff
{
    /* omitted */
    public int CarId { get; set; }
}

class Queries
{
    public Task<SomeCaculatedStuff> CalculateStuffAsync(/* omitted */)
        => /* omitted */;
}

In case above Car is used inside another object which is constructed outside IQueryable. Even though I can create a data loader that will load a Car for a SomeCalculatedStuff I cannot progress any further. When client queries calculateStuff it's prevented from querying anything more than direct properties of the Car.

The solution you'd like

Ability to mark a resolver as a fallback, or ignored in projection context.

public class CarExtensions
{
    [ProjectInsteadIfPossible]
    public Task<Brand> GetBrandAsync([Parent] Car car, [DataLoader] BrandLoader loader)
        => loader.LoadAsync(car.BranchId);
}

Now if Brand is resolved in Projection context (in a tree that begins with UseProjection), resolver won't be called and Brand will be queried in Select (in projection).

And if Brand is queried outside Projection context, resolver get's called.

Product

Hot Chocolate

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the sample query with the shown Car, Brand, UseProjection, and DataLoader setup, then trace how projection and field resolvers are selected. No implementation file or test is named in the issue, so identify the relevant projection and resolver entry points before defining coverage. Done means a fallback resolver is used outside projection while the projected field remains selected in projection contexts, without parallel schema fields.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, graphql
Domain
api, backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.