了解如何在.Net Core和C#中使用GraphQL


GraphQL是由Facebook创建的这项技术,它使前端能够与后端协商所需的数据。如果您愿意,它还可以使API的构建器将来自不同API的数据拼接在一起。这是一项非常酷的技术,它不仅适用于JavaScript,您绝对可以将它用于.Net中的下一个项目。

在本文中,我们将介绍:

  • 为什么,我们为什么要这种技术来构建API
  • 什么,它包含的部分是什么
  • 演示,让我们构建一个API,并学习如何使用我们的数据源

资源

  • GraphQL.org
    这是GraphQL组织的网站。它包含有关构建GraphQL的原因,存在的类型等的大量信息。

  • NuGet包graphql-dotnet
    这是最流行的NuGet包。它包含一个README页面,可以帮助您入门,还可以演示不同类型的应用程序,例如MVC。

  • 从VS Code中的.Net Core开始
    这显示了如何在VS Code中开始使用.Net Core。

  • 我在.Net Core和VS Code上写的入门文章

我为您撰写了一系列对.Net Core感到好奇的文章。它展示了如何构建不同类型的项目,运行测试等。它甚至涵盖了如何构建无服务器API。

  • 如何在JavaScript中构建和使用GraphQL API如果您想了解JavaScript中的工作方式,请查看我编写的这些文章。

为什么,为什么我们首先需要它。 REST API有什么问题?

GraphQL允许内容协商,这意味着您只有一个端点。它还允许您准确查询所需的字段。在后端,您还可以从不同的数据源获取数据,因此对于前端开发人员和后端开发人员来说,确实有充分的理由感到兴奋。

什么,GraphQL存在哪些部分

GraphQL由模式定义组成。您可以在名为GQL,GraphQL查询语言的东西中定义该架构,但您也可以修饰类以响应某些资源(在以后的文章中更多关于那个)。

除了模式之外,还有一个称为解析器的中心概念。解析器只是一个知道如何处理传入查询的函数。解析器映射到某个资源。

然后你有一个名为GraphiQL的可视化环境,允许你运行查询。大多数GraphQL实现都带有某种形式的可视化环境。

如何查询

当你查询时,GraphQL看起来有点特别,但它很简单。要查询您要输入的资源:

{    resource } 

然而,这还不够。您还需要指定所需的列,如下所示:

{   resource {     column,     column2   } } 

要使用参数进行查询,您可以像这样输入:

{   users(id:1) {     name,     created   } } 

最终结果始终是与您的查询匹配的JSON响应,因此如果我们采用上述查询,我​​们会得到一些看起来像这样的东西:

{   "data": {     "users": ({       "name" : "chris",       "created": "2018-01-01"       })   } } 

演示 – 让我们构建一个API。

我们需要将一些GraphQL理论与代码混合在一起。因此,我们将介绍一个概念,然后显示它的代码。

建立

我们需要做以下事情

  1. 创建解决方案
  2. 创建一个控制台应用
  3. 安装GraphQL NuGet包

创建解决方案

让我们首先创建一个解决方案目录,如下所示:

mkdir demo cd demo  

接下来,让我们创建实际的解决方案文件:

dotnet new sln 

创建控制台应用程序

让我们像这样创建一个控制台项目:

dotnet new console -o App 

然后导航到它

cd App 

添加我们的GraphQL NuGet库

接下来,让我们添加我们的GraphQL NuGet包

dotnet add package GraphQL 

你好GraphQL

现在我们准备添加代码了

// Program.cs  using System; using GraphQL; using GraphQL.Types;  namespace App {   class Program   {     static void Main(string() args)     {       Console.WriteLine("Hello World!");       var schema = Schema.For(@"           type Query {               hello: String           }           ");        var root = new { Hello = "Hello World!" };       var json = schema.Execute(_ =>       {           _.Query = "{ hello }";           _.Root = root;       });        Console.WriteLine(json);     }   } } 

上面的代码中有三个有趣的部分:

  1. 声明我们的架构
  2. 定义我们的解析器
  3. 将我们的查询排除在API之外

声明我们的架构

我们输入的字符串 Schema.For 包含一些名为GQL或GraphQL查询语言的东西。它通常定义三件事:

  1. 查询,这是我们可以查询的内容
  2. 类型,我们还没有任何类型,但我们稍后会在文章中介绍。
  3. 突变,我们可以称之为语义上意味着我们会改变一些东西

让我们特别关注我们设置架构的部分:

var schema = Schema.For(@"   type Query {       hello: String   } "); 

现在我们只有 type Query 它说的是我们可以查询 hello 并且响应是字符串类型, hello: string

解决我们的查询

架构只是这个难题的一部分。另一部分是解析器代码。这段代码实际上是处理传入请求的。在我们的例子中,解析器代码如下所示:

var root = new { Hello = "Hello World!" }; 

正如我们在上面看到的,它会在我们的查询中映射一些内容 hello 并说,如果用户要求 hello,然后我们将回答 Hello World

执行查询

在下面的代码中,我们执行查询 { hello } 通过将其分配给财产 _.Query 在我们提供的lambda表达式中 schema.Execute()

var json = schema.Execute(_ => {     _.Query = "{ hello }";     _.Root = root; }); 

然后我们的查询结果被分配给 json 我们可以使用以下方法轻松将其打印到终端:

Console.WriteLine(json);  

架构优先

这是一种不同的方法,我们将使用类并装饰它们,这个想法是类将包含在我们进行查询时将用作解析器的方法。

为此,我们需要执行以下操作:

  1. 更新我们的架构,我们需要一个新的自定义类型,我们需要在它中公开它 Query

  2. 创建一些我们需要支持Type,Query和内存数据库的类

架构更新

到目前为止,我们的架构没有类型。让我们通过添加Jedi类型来改变它,让我们也将它作为我们可以查询的内容公开,如下所示:

 Schema.For(@"   type Jedi {       name: String,       side: String   }    type Query {       hello: String,       jedis: (Jedi)   }   ", _ => { _.Types.Include<Query>(); }); 

上面我们补充说 Jedi 作为一种写作类型 type Jedi 并在其中定义其属性 {}。然后我们添加 jedis 到了 Query 并说它是类型的 (Jedi) 这意味着它是一个数组 Jedi。最后我们给了我们 Schema.For() 第二个论点:

_.Types.Include<Query>(); 

这意味着我们指出了一个班级 Query 将处理所有传入的请求。我们还没有那个价格,所以让我们创建它。

创建支持类

首先我们需要上课 Query。它现在有责任处理内部的任何事情 Query 在我们的架构中,这意味着它需要处理 hellojedis。我们来看看是什么 Query 可以看起来像:

public class Query  {     (GraphQLMetadata("jedis"))     public IEnumerable<Jedi> GetJedis()      {         return StarWarsDB.GetJedis();     }      (GraphQLMetadata("hello"))     public string GetHello()      {         return "Hello Query class";     } } 

这里我们定义两种方法 GetJedis()GetHello()。注意我们如何使用装饰器 GraphQLMetadata 在每个方法上映射我们的哪个属性 Query 他们将处理。我们也看到我们打电话给一个班级 StarWarsDB 所以我们需要创建下一个:

public static IEnumerable<Jedi> GetJedis()  {     return new List<Jedi>() {         new Jedi(){ Name ="Luke", Side="Light"},         new Jedi(){ Name ="Yoda", Side="Light"},         new Jedi(){ Name ="Darth Vader", Side="Dark"}     }; } 

定义要查询的内容

让我们定义用于查询GraphQL API的查询:

{ jedis { name, side } } 

我们上面说的是我们想要查询 jedis 我们想要列 nameside。将其与SQL表达式进行比较,我们将改为输入:

SELECT name, side FROM jedis; 

让我们用我们的查询更新代码,如下所示:

var json = schema.Execute(_ => {     _.Query = "{ jedis { name, side } }"; });  Console.WriteLine(json); 

结果是:

这似乎工作正常,好吧:)

使用参数

现在我们已经做了很多工作,但我们需要能够处理参数,有时我们只想要一条记录,所以我们需要根据一个密钥过滤更大的集合。为了实现这一目标,我们需要:

  1. 更新我们的Schema以支持带参数的查询

  2. 在我们的Query类中创建一个能够解析参数的方法

  3. 验证一切正常

更新我们的架构

首先我们需要更新我们的模式,所以我们支持一个带参数的查询,如下所示:

 Schema.For(@"   type Jedi {       name: String,       side: String,       id: ID   }    type Query {       hello: String,       jedis: (Jedi),       jedi(id: ID): Jedi   }   ", _ => { _.Types.Include<Query>(); }); 

我们实际上正在做两件事。我们正在增加这个领域 id 到了 Jedi 类型。我们也在添加这一行 Query

jedi(id: ID): Jedi 

更新我们的代码
我们的绝地课没有 Id 字段,所以我们需要添加,如下:

public class Jedi  {     public int Id { get; set; }     public string Name { get; set; }     public string Side { get; set; } } 

接下来我们需要在查询类中添加一个方法,如下所示:

(GraphQLMetadata("jedi")) public Jedi GetJedi(int id) {     return StarWarsDB.GetJedis().SingleOrDefault(j => j.Id == id); } 

请注意上面我们只需要命名匹配 id 作为输入参数。代码本身只是一个 SingleOrDefault linq查询,它给我们一个条目返回。

更新查询

让我们尝试查询这个新资源,如下所示:

{ jedi(id: 1) { name } } 

结果:

工作!!! 🙂

摘要

我们已经涵盖了很多方面。我们已经介绍了GQL,GraphQL查询语言。此外,我们还学习了如何在模式中定义资源,自定义类型以及如何解决这些问题。关于GraphQL还有很多东西需要学习,但本文已经足够长了。我希望这是一个有趣的第一眼看。在下一部分中,我们将介绍如何构建无服务器API并以这种方式利用GraphQL并将其部署到云。

资讯来源:由0x资讯编译自DEV,原文:https://dev.to/dotnet/learn-how-you-can-use-graphql-in-net-core-and-c-4h96 ,版权归作者所有,未经许可,不得转载
你可能还喜欢