使用OdataToEntity运行GraphQL查询


本文介绍如何将GraphQL查询转换为OData并通过编写来执行它们
相当多的C#代码。


如何运作


该项目的主要思想是将GraphQL查询转换为OData,将OData查询转换为表达式树,然后将其转换为ORM查询。 使用GraphQL for .NET完成GraphQL查询的解析和结果序列化。 OData查询解析是使用OData .NET库完成的 。 查询的翻译(GraphQL-> OData->表达式树)及其执行是使用OdataToEntity进行的


通过执行结果表达式树的ORM可以直接访问数据。 通过抽象类OeDataAdapter及其实现可对各种ORM进行查询:


  1. 实体框架OeEf6DataAdapter
  2. 实体框架核心OeEfCoreDataAdapter
  3. Linq2Db OeLinq2DbDataAdapter

用户只需要具有数据访问上下文(EF / EF Core-DbContext,Linq2Db-DataConnection)。
您可以在上一篇文章OdataToEntity中了解有关运行OData查询的更多信息, OdataToEntity是创建.Net Core OData服务的一种简便方法


使用范例


例如,我们将使用Star Wars模式,ORM EF Core,内存提供程序中的SQLite。


首先,您需要创建一个StarWarsContext数据访问上下文。 然后, StarWarsDataAdapter数据访问适配器。 在您可以开始执行请求之后:


String query = @" { human(id: ""1"") { name friends { name appearsIn { name } } } } "; //create data adapter var dataAdapter = new StarWars.StarWarsDataAdapter(false, "test"); //build odata model IEdmModel edmModel = dataAdapter.BuildEdmModelFromEfCoreModel(); //create graphql query parser var parser = new OeGraphqlParser(edmModel); //get graphql result ExecutionResult result = await parser.Execute(query); //serialize json String json = new DocumentWriter(true).Write(result); Console.WriteLine(json); 

GraphQL查询:


 { human(id: ""1"") { name friends { name appearsIn { name } } } } 

转换为OData:


 Human?$filter=Id eq '1'&$select=Name&$expand=Friends($select=Name;$expand=AppearsIn($select=Name)) 

转换为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) 

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" } ] } ] } ] } } 

生成的SQL不存在N + 1个查询的问题,所有数据均在一个查询中获得。


源代码结构


源代码分为两部分:在文件夹中-库本身和在test文件夹中各种数据源的访问程序集-测试和代码示例。
库本身位于source / OdataEntity.GraphQL文件夹中
测试test / OdataToEntity.Test.GraphQL
解决方案文件sln / OdataToEntity.Test.GraphQL.sln

Source: https://habr.com/ru/post/zh-CN429088/


All Articles