re: Learn how you can use GraphQL in .NET Core and C# VIEW POST

FULL DISCUSSION
 

Has anyone actually bothered figuring out how to make GraphQL efficient in .Net yet?

Using something like LINQ and EF, I can optimize my database queries to only request the data I need for a REST query - and I can do so with minimal bootstrapping.

In most situations, I can just re-use a repo or unit of work with a custom DataModel, and only have to write a simple LINQ query to get results.

I'm yet to see a GraphQL implementation which isn't simply massive amounts of extra code in the backend, with no clear approach for optimizing the database queries, and a tendency to offer mutators that require access to the majority of your database.

I wish GraphQL evangelists would stop focusing on how pretty the UI code is, when all they're doing is moving the mess somewhere else, and breaking lots of existing optimizations in doing so.

Example - check out the REST API below that looks just a firstname/lastname/id/booking-count up from a potentially heavy profile table. I'd genuinely love to see an efficient and scalable way to tackle this for GraphQL as our mobile guys are chomping at the bit for GraphQL, but I'm yet to see an approach that doesn't involve massive overhead for our team.

public class LiteProfileModel {
    public Int32 ID { get; set; }
    public String FirstName { get; set; }
    public String LastName { get; set; }
    public Int32 Bookings { get; set; }
}

public class ProfileService {
    private readonly IUnitOfWork _unitOfWork;

    public ProfileService(IUnitOfWork unitOfWork) => this._unitOfWork = unitOfWork;

    public LiteProfileModel[] GetLiteProfileByEmailAddress(String emailAddress)
    {
        return this._unitOfWork.Profiles
            .Get(filter: profile => profile
            .Where(p => p.emailAddress == emailAddress)
            .Select(p => new LiteProfileModel 
            {
                ID = p.ID,
                FirstName = p.FirstName,
                LastName = p.LastName, 
                Bookings = p.Booking.Count()
            })
            .ToArray();
    }
}



public class LiteProfileApiModel {
    public Int32 ID { get; set; }
    public String FirstName { get; set; }
    public String LastName { get; set; }
    public Int32 Bookings { get; set; }
}

public class ProfileController : ApiController
{
    private readonly IProfileService _profileService;
    private readonly IMapper _mapper;

    public ProfileController(IProfileService profileService)
    {
        var config = new MapperConfiguration(cfg => {
            cfg.CreateMap<LiteProfileApiModel, LiteProfileModel>();
        });

        this._profileService = profileService;
        this._mapper = config.CreateMapper();
    }

    public LiteProfileApiModel[] Lookup(String emailAddress)
    {
        var results = this._profileService.GetLiteProfileByEmailAddress(emailAddress);
        return this._mapper.Map<LiteProfileApiModel>(results);
    }
}
 

You have a lot of great points Peter. Let me come back to you with an article describing a nested implementation and some good practices and how to tackle the N+1 problem.. I'll say this though, you are right, you are moving the problem to somewhere else, from frontend to backend.. As always it's meant to be used in specific cases not to replace REST but coexist. I'll come back with an article in 2-3 weeks, currently on holiday

 

As always it's meant to be used in specific cases not to replace REST but coexist

Yup - my approach so far has been to provide REST APIs in the .Net portion of our stack, and allow the Swift guys to implement a GraphQL aggregator if they care enough for one.

Unfortunately, our database isn't normalized nearly as much as it should be, so pulling back entire tables hurts massively, and I'm yet to find any nice Linq2Sql or similar approaches that eliminate that as an overhead when implementing GraphQL on the .Net side.

I think this is primarily due to maturity of the toolchains, as from what I've seen, the Swift guys are going through the same overhead - it's just .Net has spent decades perfecting the REST approach to the point where I can mock one up in a comment section from memory. Our Swift guys seem to go through the same overhead regardless of REST or GraphQL at the moment however.

code of conduct - report abuse