Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A .NET Core library designed to integrate the Dapper and graphql-dotnet projects with ease-of-use in mind and performance as the primary concern.

License

NotificationsYou must be signed in to change notification settings

landmarkhw/Dapper.GraphQL

Repository files navigation

A library designed to integrate the Dapper and graphql-dotnet projects with ease-of-use in mind and performance as the primary concern.

Design

Dapper.GraphQL combines the ideas that come out-of-the-box with graphql-dotnet, and adds the following concepts:

  1. Query builders
  2. Entity mapper

Query Builders

Query builders are used to build dynamic queries based on what the client asked for in their GraphQL query. For example, given thisGraphQL query:

query {people {idfirstNamelastName    }}

A proper query builder will generate a SQL query that looks something like this:

SELECT id, firstName, lastNameFROM Person

Using the same query builder, and given the following GraphQL:

query {people {idfirstNamelastNameemails {idaddress        }phones {idnumbertype        }    }}

A more complex query should be generated, something like:

SELECTperson.Id,person.firstName,person.lastName,email.id,email.address,phone.id,phone.number,phone.typeFROM Person personLEFT OUTER JOIN Email emailONperson.Id=email.PersonIdLEFT OUTER JOIN Phone phoneONperson.Id=phone.PersonId

Entity Mappers

Entity mappers are used to map entities to Dapper from query results. Since a single entity can be composed of multiple rows of a query result, an entity mapper is designed to quickly merge multiple rows of output SQL into a single hierarchy of entities.

See thePersonEntityMapper.cs class in the test project for an example.

Usage

Setup

Dapper.GraphQL uses Microsoft's standard DI container, IServiceCollection, to manage all of the Dapper and GraphQL interactions.If you're developing in ASP.NET Core, you can add this to the ConfigureServices() method:

serviceCollection.AddDapperGraphQL(options=>{// Add GraphQL typesoptions.AddType<CompanyType>();options.AddType<EmailType>();options.AddType<PersonType>();options.AddType<GraphQL.PhoneType>();options.AddType<PersonQuery>();// Add the GraphQL schemaoptions.AddSchema<PersonSchema>();// Add query builders for dapperoptions.AddQueryBuilder<Company,CompanyQueryBuilder>();options.AddQueryBuilder<Email,EmailQueryBuilder>();options.AddQueryBuilder<Person,PersonQueryBuilder>();options.AddQueryBuilder<Phone,PhoneQueryBuilder>();});

Queries

When creating a SQL query based on a GraphQL query, you need 2 things to build the query properly: Aquery builder andentity mapper.

Query builder

Each entity in a system should have its own query builder, so any GraphQL queries that interact with those entities can be automaticallyhandled, even when nested within other entities.

In the above setup, theEmail query builder looks like this:

publicclassEmailQueryBuilder:IQueryBuilder<Email>{publicSqlQueryContextBuild(SqlQueryContextquery,IHaveSelectionSetcontext,stringalias){// Always get the ID of the emailquery.Select($"{alias}.Id");// Tell Dapper where the Email class begins (at the Id we just selected)query.SplitOn<Email>("Id");varfields=context.GetSelectedFields();if(fields.ContainsKey("address")){query.Select($"{alias}.Address");}returnquery;}}

Arguments

  • Thequery represents the SQL query that's been generated so far.
  • Thecontext is the GraphQL context - it contains the GraphQL query and what data has been requested.
  • Thealias is what SQL alias the current table has. Since entities can be used more than once (multiple entities can have anEmail, for example), it's important that our aliases are unique.

Build() method

Let's break down what's happening in theBuild() method:

  1. query.Select($"{alias}.Id"); - select the Id of the entity. This is good practice, so that even if the GraphQL query didn't include theid, we always include it.
  2. query.SplitOn<Email>("Id"); - tell Dapper that theId marks the beginning of theEmail class.
  3. var fields = context.GetSelectedFields(); - Gets a list of fields that have been selected from GraphQL.
  4. case "address": query.Select($"{alias}.Address"); - Whenaddress is found in the GraphQL query, add theAddress to the SQL SELECT clause.

Query builder chaining

Query builders are intended to chain, as our entities tend to have a hierarchical relationship. See thePersonQueryBuilder.cs file in the test project for a good example of chaining.

GraphQL integration

Here's an example of a query definition ingraphql-dotnet:

Field<ListGraphType<PersonType>>("people",description:"A list of people.",resolve: context=>{// Create an alias for the 'Person' table.varalias="person";// Add the 'Person' table to the FROM clause in SQLvarquery=SqlBuilder.From($"Person{alias}");// Build the query, using the GraphQL query and SQL table alias.query=personQueryBuilder.Build(query,context.FieldAst,alias);// Create a mapper that understands how to map the 'Person' class.varpersonMapper=newPersonEntityMapper();// Open a connection to the databaseusing(varconnection=serviceProvider.GetRequiredService<IDbConnection>()){// Execute the query with the person mappervarresults=query.Execute(connection,personMapper,context.FieldAst);// `results` contains a list of people.returnresults;}});

Mapping objects of the same type

The test project contains an example of how to handle this scenario. SeePersonEntityMapper.cs.

Examples

See the Dapper.GraphQL.Test project for a full set of examples, including howquery builders andentity mappers are designed.

Development & Testing

To run unit tests, you must have PostgreSQL running locally on your machine. The easiest way toaccomplish this is to install Docker and run PostgreSQL from the official Docker container:

From a command line, run a Postgres image from docker as follows:

docker run --name dapper-graphql-test -e POSTGRES_PASSWORD=dapper-graphql -d -p 5432:5432 postgres

Then, unit tests should function as expected.

Roadmap

  • Fluent-style pagination

About

A .NET Core library designed to integrate the Dapper and graphql-dotnet projects with ease-of-use in mind and performance as the primary concern.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors7

Languages


[8]ページ先頭

©2009-2025 Movatter.jp