0
I have the following GrapqhQL query:
query {
listTenants {
totalCount
items {
tenantId
name
sites {
totalCount
items {
siteId
cmxName
cmxState
hosts(
order: { hostId: ASC }
where: { hostName: { neq: "ans" } }
skip: 4
take: 2
) {
totalCount
items {
hostId
hostName
siteId
}
}
}
}
}
}
}
I want to use projections for the host object – I want to extract from the database only the hostId, hostName and siteId for each host. I extend the Site object type as follows:
namespace dataGraphAPI.Types.Nodes
{
[ExtendObjectType<Site>]
public static class SiteNode
{
[GraphQLName(SchemaConstants.Hosts)]
[ListQueries]
public static async Task<IEnumerable<Host>> GetHostsAsync(
[Parent] Site site,
IHostsBySiteIdDataLoader dataLoader,
CancellationToken ct)
=> await dataLoader.LoadAsync(site.SiteId.ToString(), ct);
}
}
My [ListQueries] attribute contains the following attributes:
using HotChocolate.Types.Descriptors;
using System.Reflection;
namespace dataGraphAPI.Types
{
public sealed class ListQueriesAttribute : ObjectFieldDescriptorAttribute
{
protected override void OnConfigure(IDescriptorContext context, IObjectFieldDescriptor descriptor, MemberInfo member)
{
ApplyAttribute(
context,
descriptor,
member,
new UseOffsetPagingAttribute()
{
IncludeTotalCount = true,
});
ApplyAttribute(
context,
descriptor,
member,
new UseProjectionAttribute());
ApplyAttribute(
context,
descriptor,
member,
new UseFilteringAttribute());
ApplyAttribute(
context,
descriptor,
member,
new UseSortingAttribute());
}
}
}
My data loader is as follows:
[DataLoader]
internal static async Task<ILookup<string, Host>> GetHostsBySiteIdAsync(IReadOnlyList<string> siteIds, CmxDbContext dbContext, CancellationToken ct)
{
var hosts = dbContext.Hosts
.Where(x => siteIds.Contains(x.SiteId.ToString()));
return hosts.ToLookup(x => x.SiteId.ToString()!);
}
My Program.cs is as follows:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<CmxDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("CMXContext"))
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
.LogTo(Console.WriteLine, LogLevel.Information));
builder.Services
.AddGraphQLServer()
.AddTypes()
.AddType<AggregateResult>()
.AddType<CountResult>()
.AddType<DistinctResult>()
.AddDirectiveType<AggregateDirectiveType>()
.AddDirectiveType<CountDirectiveType>()
.AddDirectiveType<DistinctDirectiveType>()
.AddFiltering()
.AddSorting()
.AddProjections()
.RegisterDbContext<CmxDbContext>();
var app = builder.Build();
app.MapGraphQL();
app.Run();
The problem is that when I extract the hosts from the database the UseProjectionAttribute which is set in the ListQueriesAttribute does not work and I retrieve all the columns for each host from the database, not only the hostId, hostName and siteId. I am kind of new to data loaders and HotChocolate, so I may be doing something wrong. I understand that [UseProjection] works for IQueryable, but it seems to me that there is no way to return IQueryable with data loaders, hence I cannot apply the attribute to the data loader. Any suggestions how I can make this work with projections?
|