تشغيل استعلامات GraphQL مع OdataToEntity


توضح المقالة كيفية ترجمة استعلامات GraphQL إلى OData وتنفيذها عن طريق الكتابة
القليل من كود C #.


كيف يعمل


الفكرة الرئيسية للمشروع هي ترجمة استعلامات GraphQL إلى OData ، ترجمة استعلامات OData إلى شجرة تعبير ، والتي يتم ترجمتها بعد ذلك إلى استعلام عن ORM. يتم تحليل استعلام GraphQL وتسلسل نتائجه باستخدام GraphQL for .NET . يتم تحليل استعلام OData باستخدام مكتبات OData .NET . ترجمة الاستعلام (GraphQL -> OData -> شجرة التعبير) وتنفيذها باستخدام OdataToEntity .


يتم الوصول المباشر إلى البيانات من خلال ORM تنفيذ شجرة التعبير الناتجة. يتم تنفيذ الاستعلامات على مختلف ORMs من خلال الفئة المجردة OeDataAdapter وتنفيذها من أجل:


  1. إطار الكيان OeEf6DataAdapter
  2. إطار عمل الكيان الأساسي OeEfCoreDataAdapter
  3. Linq2Db OeLinq2DbDataAdapter

يحتاج المستخدم فقط إلى سياق الوصول إلى البيانات (EF / EF Core - DbContext ، Linq2Db - DataConnection).
لمزيد من المعلومات حول تنفيذ استعلامات OData ، راجع مقالتي السابقة ، OdataToEntity ، وهي طريقة سهلة لإنشاء .Net Core OData services .


مثال للاستخدام


على سبيل المثال ، سنستخدم مخطط حرب النجوم ، 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 ، يتم الحصول على جميع البيانات في استعلام واحد.


هيكل كود المصدر


ينقسم رمز المصدر إلى جزأين: في المجلد المصدر - المكتبة نفسها وتجميعات الوصول لمصادر البيانات المختلفة ، في مجلد الاختبار - الاختبارات وأمثلة التعليمات البرمجية.
تقع المكتبة نفسها في مجلد المصدر / OdataEntity.GraphQL .
اختبارات الاختبارات / OdataToEntity.Test.GraphQL .
ملف الحل sln / OdataToEntity.Test.GraphQL.sln .

Source: https://habr.com/ru/post/ar429088/


All Articles