DEV Community

Cover image for Learn how you can use GraphQL in .NET Core and C#

Learn how you can use GraphQL in .NET Core and C#

Chris Noring on August 02, 2019

GraphQL is this technology created by Facebook that enables the frontend to negotiate with the backend for what data it wants. It also enables the...
Collapse
 
dolkensp profile image
Peter Dolkens • Edited

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);
    }
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
softchris profile image
Chris Noring

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

Collapse
 
dolkensp profile image
Peter Dolkens • Edited

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.

Collapse
 
yakimych profile image
Kyrylo Yakymenko

Thanks for the post! Have you had time to write a follow-up article on this? I am particularly curious about tackling the N+1 problem myself.
Also, if you have any tips about implementing a Relay-compatible GraphQL server in .NET (C# or F#), that would be really helpful!

Collapse
 
pvanroos profile image
Paul VanRoosendaal

Are you looking for a GraphQL to LINQ translation? Aren't there some libs for that?

Collapse
 
ronaldoperes profile image
Ronaldo Peres

Hi,

Is there an effective way of using GraphQl with MongoDb?

Collapse
 
softchris profile image
Chris Noring

is this for .NET or? you could be using this github.com/remorses/mongoke to expose your database as a GraphQL API or have a look here if you just want a tutorial on how to use it dev.to/alvarojsnish/graphql-mongod... . Let me know what you had in mind ? :)

Collapse
 
ronaldoperes profile image
Ronaldo Peres

Well,

I am thinking to use GraphQl with Dotnet Core, for example: if I have a collection in mongo of games - how to use GraphQl to retrieve data without doing a GetAll() in the collection?

Is there a way to setup the Mongodb repository in Dotnet core with GraphQl?

Thread Thread
 
softchris profile image
Chris Noring

Generally, you use a query that takes a parameter on the GraphQL side

// schema
{
  Query {
    GetCommentById(id: ID): Comment
  } 
}

// asking the query
query <name it something> {
  GetCommentById(id: 1)
}

As for dealing with .NET Core and MongoDB you have a tutorial here docs.microsoft.com/en-us/aspnet/co... . I suppose I could be writing a tutorial on GraphQL, .NET Core and MongoDB if you are interested?

Also have a look here dev.to/dotnet/how-you-can-build-a-... This shows how our request is passed from API to DB layer

Thread Thread
 
jghx profile image
jghx

I tried do to a combination of GraphQL, .NET Core and MongoDB but can seem te get the MongoDb working to you still need to use a DBContext and DBsets or can you just use IMongoCollection's like in the Microsoft tutorial?

Thread Thread
 
noamwe profile image
Noam Wertheim

Hi thank you for the links.
I would be very much interested in reading a tutorial on how to implement a GraphQl server with .NET Core and MongoDb.
So far only managed to implement it when all data sat in memory, which is of course not an acceptable solution.

Thread Thread
 
softchris profile image
Chris Noring

I'm looking into a GraphQL solution currently called Hot Chocolate. It has the concept of loaders. Yes some data need to sit in memory, but not all. Maybe that can offer a path forward? hotchocolate.io/docs/introduction....

Collapse
 
daniel15 profile image
Daniel Lo Nigro

Great post!

Just a small note:

It's a very cool piece of technology and it's not just for JavaScript

Note that the original use case for GraphQL wasn't JavaScript, it was Facebook's native mobile apps :)
It evolved to JavaScript later on, once Relay (and then Apollo) were released.

Collapse
 
softchris profile image
Chris Noring

Didn't know that, thanks Daniel :)

Collapse
 
nishcooly profile image
Nishant Koli

Thank you for this amazing tutorial. I am a frontend dev trying to understand and implement a backend with graphql.

Forgive me for being naive, but I wanted to know how this is different from a REST api as we are still writing predefined queries to fetch from the db.

Collapse
 
markpieszak profile image
Mark Pieszak • Edited

Great post as always 🙌👏!
I've actually never had a chance to see/try GraphQL with DotNet yet.

Most DotNet shops typically only do REST APIs unfortunately! :(

How is the intellisense with the Queries themselves?

Collapse
 
softchris profile image
Chris Noring

Well there is the visual GraphiQL NuGet package that will do that :)

Collapse
 
danharries profile image
Dan Harries

Hi Chris,

I barely comment on dev posts but really like your writing style, very clear and concise.

Keep up the good work 🙂

Collapse
 
softchris profile image
Chris Noring

Hi Dan, really appreciate your comment, thank you :)

Collapse
 
leeoades profile image
Lee Oades

Great article. Really enjoyed the writing style and pace. Quick typo : "Exuting our query the API"

Collapse
 
mrinatra profile image
Mrinal Patra

Great post to get started on GraphQL! I couldn't figure out how to use the DataLoader to batch requests.

Is it possible to have a small example of DataLoader in your follow up post?

Collapse
 
softchris profile image
Chris Noring

Hi thanks Mrinal. Let me see what I can do :)

Collapse
 
andres profile image
Andrés Pérez

Lovely post, would be amazing to see a follow-up GraphQL + ASP.NET Core article :)

Collapse
 
softchris profile image
Chris Noring

should be coming out next week :)

Collapse
 
carlsixsmith profile image
Carl Sixsmith

Great post, look forward to seeing the next one.

This could be exceeding useful for what I’m currently working on

Collapse
 
pwnchaurasia profile image
Pawan Chaurasia

Can you do a graphQL and elastic search tutorial. to access nested data in elasticsearch

Collapse
 
brunotdantas profile image
Bruno Dantas

.

Collapse
 
lespinter profile image
LesPinter

I was with you up until "Schema update". Where does this code go?

Collapse
 
softchris profile image
Chris Noring

we are still in Program.cs at this point. Thanks for the comment. I'll make sure to write out the file name and write out all the code, not just snippets. Have a look at this repo for a more real looking approach github.com/softchris/graphql-ef-demo

Collapse
 
ronaldoperes profile image
Ronaldo Peres

Very good,

I would like to see a tutorial to use graphql with dotnet core 3 webapi.

Regards

Collapse
 
softchris profile image
Chris Noring

hi Ronaldo. You are in luck :) dev.to/dotnet/how-you-can-build-a-...