
El art铆culo describe c贸mo traducir consultas GraphQL a OData y ejecutarlas escribiendo
bastante c贸digo de C #.
Como funciona
La idea principal del proyecto es la traducci贸n de consultas GraphQL en OData, la traducci贸n de consultas OData en un 谩rbol de expresi贸n, que luego se traduce en una consulta para ORM. El an谩lisis de una consulta GraphQL y la serializaci贸n de sus resultados se realiza utilizando GraphQL para .NET . El an谩lisis de consultas de OData se realiza utilizando las bibliotecas .NET de OData . La traducci贸n de consultas (GraphQL -> OData -> 谩rbol de expresi贸n) y su ejecuci贸n se lleva a cabo utilizando OdataToEntity .
El acceso directo a los datos se lleva a cabo a trav茅s del ORM que ejecuta el 谩rbol de expresi贸n resultante. Las consultas en varios ORM se ejecutan a trav茅s de la clase abstracta OeDataAdapter y su implementaci贸n para:
- Entity Framework OeEf6DataAdapter
- Entity Framework Core OeEfCoreDataAdapter
- Linq2Db OeLinq2DbDataAdapter
El usuario solo necesita tener un contexto de acceso a datos (EF / EF Core - DbContext, Linq2Db - DataConnection).
Puede leer m谩s sobre c贸mo ejecutar consultas OData en mi art铆culo anterior, OdataToEntity, una manera f谩cil de crear servicios .Net Core OData .
Ejemplo de uso
Por ejemplo, utilizaremos el esquema de Star Wars , ORM EF Core, el proveedor de SQLite en memoria.
Primero debe crear un contexto de acceso a datos de StarWarsContext . Luego, el adaptador de acceso a datos StarWarsDataAdapter . Despu茅s de que pueda comenzar a ejecutar la solicitud:
String query = @" { human(id: ""1"") { name friends { name appearsIn { name } } } } ";
Consulta GraphQL:
{ human(id: ""1"") { name friends { name appearsIn { name } } } }
Traducido a OData:
Human?$filter=Id eq '1'&$select=Name&$expand=Friends($select=Name;$expand=AppearsIn($select=Name))
Traducido a SQL:
SELECT "h"."Name" AS "Item1", "h"."Id" AS "Item2", CASE WHEN "t"."Id" IS NULL THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END, "t"."Name" AS "Item10", "t"."Id" AS "Item20", CASE WHEN "EpisodeEnum"."Value" IS NULL THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END, "EpisodeEnum"."Name" AS "Item11", "EpisodeEnum"."Value" AS "Item21" FROM "Hero" AS "h" LEFT JOIN "HeroToHero" AS "CharacterToCharacter" ON "h"."Id" = "CharacterToCharacter"."CharacterId" LEFT JOIN ( SELECT "Hero".* FROM "Hero" AS "Hero" WHERE "Hero"."CharacterType" IN (1, 2) ) AS "t" ON "CharacterToCharacter"."FriendId" = "t"."Id" LEFT JOIN "HeroToEpisode" AS "CharacterToEpisode" ON "t"."Id" = "CharacterToEpisode"."CharacterId" LEFT JOIN "Episodes" AS "EpisodeEnum" ON "CharacterToEpisode"."EpisodeId" = "EpisodeEnum"."Value" WHERE ("h"."CharacterType" = 1) AND ("h"."Id" = @__Item1_0)
Resultado JSON:
{ "data": { "human": [ { "name": "Luke", "friends": [ { "name": "R2-D2", "appearsIn": [ { "name": "NEWHOPE" }, { "name": "EMPIRE" }, { "name": "JEDI" } ] }, { "name": "C-3PO", "appearsIn": [ { "name": "NEWHOPE" }, { "name": "EMPIRE" }, { "name": "JEDI" } ] } ] } ] } }
El SQL generado no tiene un problema de consultas N + 1, todos los datos se obtienen en una consulta.
Estructura del c贸digo fuente
El c贸digo fuente se divide en dos partes: en la carpeta fuente , la biblioteca en s铆 y los ensambles de acceso a varias fuentes de datos, en la carpeta de prueba , ejemplos de pruebas y c贸digos.
La biblioteca en s铆 se encuentra en la carpeta fuente / OdataEntity.GraphQL .
Prueba de pruebas / OdataToEntity.Test.GraphQL .
El archivo de soluci贸n sln / OdataToEntity.Test.GraphQL.sln .