1

I have posted the issue to HC directly, but hoping to get some help from SO: https://github.com/ChilliCream/graphql-platform/issues/5827

I've added AutoMapper to our HC 12 + EF Core 7 project to complicate things a bit more. After lots of self reflection I finally got everything setup and projections / overfetching working by following this issue #4724 and a few others. Maybe my issue is related to some of the last minute warnings in the last comment?

My present issue is that sometimes filtering is not translated the way I'd expect and instead I get an Exception from EF.

I get this error when I filter on the disabled property vs the id or name properties:

{
  sites(where: { disabled: { eq: 1 } }) {
    id
    name
  }
}
System.InvalidOperationException: 'The LINQ expression 'DbSet<InventSite>()
    .Where(i => new LazySite{ 
        Id = Convert.ToInt32(i.SiteId), 
        Name = i.Name 
    }
    .Disabled == __p_0)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.'

However, if I filter another field it's OK

{
  sites(where: { id: { eq: 1 } }) {
    id
    name
  }
}

projects the proper SQL:

SELECT CONVERT(int, [i].[SiteID]) AS [Id], [i].[Name]
FROM [dbo].[InventSite] AS [i]
WHERE CONVERT(int, [i].[SiteID]) = @__p_0

Below is my project setup

Project Setup

My DTO

public class InventSite
{
    public string DataAreaId { get; set; } = null!;
    public string SiteId { get; set; } = null!;
    public string? Dimension4 { get; set; }
    public string? Name { get; set; }
    public int Disabled { get; set; }
}

My exposed Graph entity

public class LazySite
{
    public int Id { get; init; }
    public int? AxSiteId { get; init; }
    public string? Name { get; init; }
    public int Disabled { get; init; }
}

AutoMapper profile

public MappingProfile()
    {
        CreateMap<InventSite, LazySite>()
            .ForMember(d => d.Id, e => e.MapFrom(s => Convert.ToInt32(s.SiteId)))
            .ForMember(d => d.AxSiteId, e => e.MapFrom(s => !string.IsNullOrWhiteSpace(s.Dimension4) ? (int?)Convert.ToInt32(s.Dimension4) : null))
            //.ForMember(d => d.Disabled, e => e.MapFrom(s => s.Disabled))
            .ForAllMembers(i => i.ExplicitExpansion());
    }

Query

public class Query
{
    [Authorize]
    [UseProjection]
    [UseFiltering]
    [UseSorting]
    public IQueryable<LazySite> GetSites([Service] ISiteService siteService, IResolverContext resolverContext)
        => siteService.GetSites(resolverContext);
}

// ISiteService method:
public IQueryable<LazySite> GetSites(IResolverContext resolverContext)
        => _edrHelper.GetSites().ProjectTo<InventSite, LazySite>(resolverContext);

// IEdrHelper here
public IQueryable<InventSite> GetSites() =>
        _context.InventSites.AsNoTracking();
Poat
  • 327
  • 1
  • 11
  • 3
    Apparently the problem is with filter fields which are not included in the result. And the reason is the way HC builds the query when combined with AM - projection first (using explicit mapping, i.e. include only the specified fields), then filter. While as I understand, w/o AM they use filter first, then projection. That's why the manual `Select` approach works. Or because in manual approach you include all the fields in the select. Remove AM explicit expansion or do not use AM or wait HC to resolve it (if they can and willing to). – Ivan Stoev Feb 11 '23 at 06:06
  • https://docs.automapper.org/en/latest/Queryable-Extensions.html#query-provider-limitations – Lucian Bargaoanu Feb 11 '23 at 06:31
  • 1
    @IvanStoev WOW! yes that was it! I can live with that limitation for now since the API is internal.. you saved me needing to rip out AM - CHEERS! – Poat Feb 12 '23 at 20:32

0 Answers0