GraphQL.RepoDB
A set of extensions for working with HotChocolate GraphQL and Database access with micro-orms such as RepoDb (or Dapper). This extension pack provides access to key elements such as Selections/Projections, Sort arguments, & Paging arguments in a significantly simplified facade so this logic can be leveraged in the Serivces/Repositories that encapsulate all data access (without dependency on IQueryable and execution outside of the devs control).
Install / Use
/learn @cajuncoding/GraphQL.RepoDBREADME
Overview
(Unofficial) HotChocolate v11/v12 Extension Pack for working with Micro-ORM(s) and encapsulated data access (instead of IQueryable).
This library greatly simplifies working with HotChocolate to resolver processes data for selecting/projecting, sorting, paging, etc. before returning the data to HotChocolate from the resolver; this is in contrast to the often documented deferred execution via IQueryable whereby control over the execution is delegated to the HotChocolate (& EntityFramework) internals.
By providing a facade that enables easier selections, projections, and paging inside the resolver this library greatly simplifies working with HotChocolate GraphQL and Database access with micro-orms such as RepoDb (or Dapper). This extension pack provides access to key elements such as Selections/Projections, Sort arguments, & Paging arguments in a significantly simplified facade so this logic can be leveraged inside the Resolvers (and lower level Serivces/Repositories that encapsulate all data access) without dependency on IQueryable deferred execution (e.g. EntityFramework).
In addition, for RepoDb specifically, a full implementation is provided along with additional RepoDb extension methods for efficient/easy Cursor Pagination and is built completely on top of the graphql.ResolverProcessingExtensions.
Buy me a Coffee ☕
I'm happy to share with the community, but if you find this useful (e.g for professional use), and are so inclinded, then I do love-me-some-coffee!
<a href="https://www.buymeacoffee.com/cajuncoding" target="_blank"> <img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"> </a>GraphQL.ResolverProcessingExtensions
A set of extensions for working with HotChocolate GraphQL and Database access with micro-orms such as RepoDb (or Dapper). Micro ORMs normally require (and encourage) encapsulated data access that resolver processes the results prior to returning results from the resolvers to HotChocolate.
This is in contrast to how many existing tutorials illustrate deferred execution of database queries via IQueryable. Because IQueryable is pretty much only supported by Entity Framework, it may be incongruent with existing tech-stacks and/or be much to large (bloated) of a dependency -- in addition to removing control over the SQL queries.
In these cases, and in other cases where existing repository/service layer code already exists, the data is 'resolver processed', and is already filtered, sorted, paginated, etc. before being returned from the graphql resolvers.
This extension pack provides access to key elements such as Selections/Projections, Sort arguments, & Paging arguments in a significantly simplified facade so this logic can be leveraged in the Serivces/Repositories that encapsulate all data access (without dependency on IQueryable and execution outside of the devs control).
Nuget Package (>=netstandard2.1)
To use this in your project, add the graphql.PreprocessingExtensions NuGet package to your project, wire up your Starup middleware, and inject / instantiate params in your resolvers as outlined below...
graphql.RepoDb.SqlServer
A set of extensions for working with HotChocolate GraphQL and RepoDb as the data access micro-orm without dependency on IQueryable. This enables fully encapsulated control over SQL queries in every way within a Service or Repository layer of your application.
This extension pack provides a significantly simplified facade to access critial elements such as Selections/Projections, Sort arguments, & Paging arguments with support for mapping them to Models using built in RepoDb functionality. It also leverages RepoDb to provide a generic, Relay spec compatible, cursor pagination/slice query api for Sql Server.
Nuget Package (>=netstandard2.1)
To use this in your project, add the graphql.RepDb.SqlServer NuGet package to your project, wire up your Starup middleware, and inject / instantiate params in your resolvers as outlined below...
Release Notes v12.4.1.0:
- Updated to latest version of HC v12.4.1 stable
- Fixed breaking change in HC where Field Definition context data methods were removed; now uses the new pattern that HC Core attributes (e.g. UsePaging, UseSorting).
- Updated Demo projects to .Net 6.0 and Azure Functions v4.
- Bump RepoDB (Sql Server) version to v1.1.4 stable
Prior Release Notes:
- Added full support for Offset Paging with RepoDB.
- Optimized the RepoDB extensions Cursor paging algorithm to no longer require the TotalCount to safely determine HasNextPage & HasPreviousPage paging metadata; this helps optimize both Cursor Paging and Offset paging queries.
- Added RepoDB support for of the new graphqlParamsContext.IsTotalCountRequested property so that we now only compute the Count when actually requested.
- Added full support for Offset Paging as well as CursorPaging with matching capabilities - including models, extension methods to convert from IEnumerable, etc.
- Added examples in the StarWars Azure Functions project using in-memory processing (RepoDb implementation is not complete).
- Added support to easily determine if TotalCount is selected (as it's a special case selection) to support potential performance optimizations within Resolver logic.
graphqlParamsContext.IsTotalCountRequested
- Added more Unit test coverage for Selections, and Paging implmentations
- Generic facade for resolver processed results to safely bypass the HotChocolate out-of-the-box pipeline (IQueryable dependency) for Sorting & Paging; eliminatues redundant processing and possilby incorrect results from re-processing what has already been 'resolver processed'.
- Supports encapsulated service/repository pattern whereby all data retrieval is owned in the same portable layer, and not dependent on HotChocolate internal procesing via IQueryable.
- Provides abstraction facade with graphql.ResolverProcessingExtensions package that can be used for any micro-orm.
- Implemented RepoDb on top of graphql.ResolverProcessingExtensions, as a great primary DB interface with helper classes for mapping Selections from GraphQL to DB layer: (graphql Schema names -> Model properties -> DB Column names).
- Supports abstracted facade for:
- Projections of Selection (SELECT X, Fields) down to the Repository Layer and therefore down to the SQL Queries themselves via RepoDb -- works correctly with GraphQL Objects (classes), and now GraphQL Interfaces with query fragments (C# interfaces) too! And supports correct GraphQL Schema to Class property mapping.
- Support for Sorting arguments down to the Repository/Service layer & into Sql queries via RepoDb -- with full GraphQL Schema to Class property mapping.
- Support for Cursor based Pagination arguments down to the the Repository/Service layer & into Sql queries via RepoDb -- Relay spec cursors are fully implemented via Sql Server api extensions to RepoDb.
- Implemented configuration based control over Projection Dependencies and Pure Code First Attribute to simplify this -- so if a child or virtual field resolver needs a field of the parent, but it wasn't actually part of the selection from the client's query, it is added to the Selections if/when it is necessary.
- Fixed/Changed repo & package names to address conflicts with HotChocolate core packages.
Planned:
- Support for enhanced ability to work with Dynamic Filtering (WHERE clause) arguments; support will be added as time permits.
- TODO: Improved support for field selections with Mutations.
Demo Site (Star Wars)
This project provides multiple versions of the HotChocolate GraphQL Star Wars example project using the Pure Code First approach.
Each of the examples are setup to run as an AzureFunctions app and updated/enhanced to use the new v11 API along with example cases
for the various features of this package -- CharacterQueries and CharacterRepository now all use RepoDb and ResolverProcessing extensions
to push logic down to be encapsulated in the data access layer.
Two versions of the Example Project included:
- StarWars-AzureFunctions: A version using Resolver Processing extensions only along with in-memory processing with Linq over IEnumerable, but all encapsulated in the Query/Repository layer and no longer using the IQueryable interface. This simulates the use of lower layer logic for Sorting, Paging, etc. as you would with a micro-orm for working with an external data source, and helps show how any micro-orm or other functionality can now leverage the simplified facade to HotChocolate provided by graphql.ResolverProcessingExtensions.
- StarWars-AzureFunctions-RepoDb: A version that does the above but implements RepoDb as a fully fledged micro-orm implemenation.
And illustrates a number of related features to show its use in multiple typs of Resolvers (Attribute, and virtual field resolvers), with and without ProjectionDependencies, nested Paging and Sorting, etc. with all logic encapsulated in the Query
and Repository layer with no dependency on IQueryable.
- As a fully integrated DB example, the schema & sample data has been scripted and provided in: DatabaseScripts/CreateStarWarsSchema.sql
NOTES:
- NOTE: This is not necessarily the only, nor do I claim it's the best, approach to working with GraphQL or HotChocolate specifically -- but it greatly simplifies the amount of work and effort needed to use it in with a Service or Repository pattern of encapsulated data access.
- In most enterprises it's very common to have constraints such as:
- Existing logic that needs to be re-used from business layer, and/or existing service or
- repository classes.
- Properl
