Führen Sie GraphQL-Abfragen mit OdataToEntity aus


    In diesem Artikel wird beschrieben, wie GraphQL-Abfragen in OData übersetzt und ausgeführt werden, indem
    viel C # -Code geschrieben wird.


    Wie funktioniert das?


    Die Hauptidee des Projekts ist die Übersetzung von GraphQL-Abfragen in OData, die Übersetzung von OData-Abfragen in einen Ausdrucksbaum, die dann in eine Abfrage für ORM übersetzt wird. GraphQL-Abfrageanalyse und ihre Ergebnisse werden mit GraphQL für .NET serialisiert . Eine OData-Anforderung wird mithilfe der OData .NET-Bibliotheken analysiert . Die Abfrageübersetzung (GraphQL -> OData -> Ausdrucksbaum) und ihre Ausführung wird mit OdataToEntity ausgeführt .


    Der direkte Zugriff auf die Daten erfolgt über den ORM, wobei der resultierende Ausdrucksbaum (Ausdrucksbaum) ausgeführt wird. Abfragen zu verschiedenen ORMs werden über die abstrakte Klasse OeDataAdapter und deren Implementierung für Folgendes durchgeführt:


    1. Entity Framework OeEf6DataAdapter
    2. Entity Framework Core OeEfCoreDataAdapter
    3. Linq2Db OeLinq2DbDataAdapter

    Der Benutzer muss lediglich über einen Datenzugriffskontext verfügen (EF / EF Core - DbContext, Linq2Db - DataConnection).
    Weitere Informationen zur Ausführung von OData-Anforderungen finden Sie in meinem vorherigen Artikel OdataToEntity, einer einfachen Methode zum Erstellen von .Net Core OData-Services .


    Verwendungsbeispiel


    Beispielsweise wird der Star Wars- , ORM-EF-Core- und SQLite-Speicheranbieter verwendet .


    Zuerst müssen Sie einen Datenzugriffskontext StarWarsContext erstellen . Dann den Datenzugriffsadapter StarWarsDataAdapter . Nachdem Sie die Abfrage ausführen können:


    String query = @"
        {
            human(id: ""1"") {
              name
              friends {
                name
                appearsIn {
                   name
                }
              }
           }
        }
    ";
    //create data adaptervar dataAdapter = new StarWars.StarWarsDataAdapter(false, "test");
    //build odata model
    IEdmModel edmModel = dataAdapter.BuildEdmModelFromEfCoreModel();
    //create graphql query parservar 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-Abfrage:


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

    Übertragung an OData:


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

    Übertragung an SQL:


    SELECT"h"."Name"AS"Item1",
    "h"."Id"AS"Item2",
    CASEWHEN"t"."Id"ISNULLTHENCAST(1ASBIT) ELSECAST(0ASBIT)
    END,
    "t"."Name"AS"Item10",
    "t"."Id"AS"Item20",
    CASEWHEN"EpisodeEnum"."Value"ISNULLTHENCAST(1ASBIT) ELSECAST(0ASBIT)
    END,
    "EpisodeEnum"."Name"AS"Item11",
    "EpisodeEnum"."Value"AS"Item21"FROM"Hero"AS"h"LEFTJOIN"HeroToHero"AS"CharacterToCharacter"ON"h"."Id" = "CharacterToCharacter"."CharacterId"LEFTJOIN (
        SELECT"Hero".*
        FROM"Hero"AS"Hero"WHERE"Hero"."CharacterType"IN (1, 2)
    ) AS"t"ON"CharacterToCharacter"."FriendId" = "t"."Id"LEFTJOIN"HeroToEpisode"AS"CharacterToEpisode"ON"t"."Id" = "CharacterToEpisode"."CharacterId"LEFTJOIN"Episodes"AS"EpisodeEnum"ON"CharacterToEpisode"."EpisodeId" = "EpisodeEnum"."Value"WHERE ("h"."CharacterType" = 1) AND ("h"."Id" = @__Item1_0)

    JSON-Ergebnis:


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

    Die generierte SQL hat nicht das Problem von N + 1-Abfragen. Alle Daten werden in einer einzigen Abfrage abgerufen.


    Quelltextstruktur


    Der Quellcode ist in zwei Teile unterteilt: in einem Ordner -source - die Bibliothek selbst und den Zugriff auf verschiedene Datenquellen aufzubauen, in dem Ordner Test - Tests und Code - Beispiele.
    Die Bibliothek selbst befindet sich im Ordner source / OdataEntity.GraphQL .
    Tests test / OdataToEntity.Test.GraphQL .
    Bild von einer Lösung sln / OdataToEntity.Test.GraphQL.sln .


    Jetzt auch beliebt: