ASP.NET Core中使用GraphQL - 第五章 字段, 参数, 变量
ASP.NET Core中使用GraphQL
- ASP.NET Core中使用GraphQL - 第一章 Hello World
- ASP.NET Core中使用GraphQL - 第二章 中间件
- ASP.NET Core中使用GraphQL - 第三章 依赖注入
- ASP.NET Core中使用GraphQL - 第四章 GrahpiQL
字段
我们已经很好的理解了GraphQL中的字段。在之前HelloWorldQuery
的例子中,我们添加了2个字段hello
和howdy
. 它们都是标量字段。正如GraphQL官网文档中声明的那样
"At its simplest, GraphQL is about asking for specific fields on objects"
简单来说,GraphQL就是询问对象中的一些特定字段
来源: graphql.org
下面我们来为我们的实例程序添加一些复杂的类型。比如,现在我们需要编写一个库存系统,我们首先添加一个货物类Item
, 其代码如下:
public class Item
{
public string Barcode { get; set; }
public string Title { get; set; }
public decimal SellingPrice { get; set; }
}
但是我们不希望直接针对这个对象创建查询,因为它不是一个GraphQL
对象,它没有继承自ObjectGraphType
, 为了创建一个GraphQL
查询,我们需要创建一个新类ItemType
, 它继承自ObjectGraphType
类。
另外ObjectGraphType
类是一个泛型类,所以这里我们需要指定它的泛型参数是Item
public class ItemType : ObjectGraphType<Item>
{
public ItemType()
{
Field(i => i.Barcode);
Field(i => i.Title);
Field(i => i.SellingPrice);
}
}
这里有2点需要注意。首先我们不在针对字段进行类型声明了。GraphQL
库将实体类属性字段类型映射成GraphQL
的内置类型。例如这里Barcode
的类型string
会被映射成GraphQL
的内置类型StringGraphType
。其次这里我们使用了Lambda表达式设置了实体类属性和GraphQL
字段之间的映射, 这有点类似于数据库模型和ViewModel之间的转换的映射。
下一步,我们需要在HelloWorldQuery
中注册ItemType
。
public HelloWorldQuery()
{
...
...
Field<ItemType>(
"item",
resolve: context =>
{
return new Item {
Barcode = "123",
Title = "Headphone",
SellingPrice = 12.99M
};
}
);
}
这里我们暂时设置了一个硬编码的返回值。所以当查询item
对象的时候,这个硬编码的返回值会输出出来。
现在我们启动项目,进入GraphiQL
界面
首先我们设置查询为
query {
item{
barcode
sellingPrice
}
}
运行查询之后,结果是
{
"data": {
"item": {
"barcode": "123",
"sellingPrice": 12.99
}
}
}
然后我们修改查询为
query {
item{
barcode
sellingPrice
title
}
}
运行查询之后,结果是
{
"data": {
"item": {
"barcode": "123",
"sellingPrice": 12.99,
"title": "Headphone"
}
}
}
这说明我们的GraphQL
查询已经生效,api根据我们需要的字段返回了正确的返回值。
参数
这里我们可以使用参数去除前面的硬编码。
为了说明如何使用参数,这里我们首先创建一个数据源类DataSource
, 其代码如下
public class DataSource
{
public IList<Item> Items
{
get;
set;
}
public DataSource()
{
Items = new List<Item>(){
new Item { Barcode= "123", Title="Headphone", SellingPrice=50},
new Item { Barcode= "456", Title="Keyboard", SellingPrice= 40},
new Item { Barcode= "789", Title="Monitor", SellingPrice= 100}
};
}
public Item GetItemByBarcode(string barcode)
{
return Items.First(i => i.Barcode.Equals(barcode));
}
}
这里除了Items
集合,我们还添加了一个方法GetItemByBarcode
, 这个方法可以根据传递的barcode
参数返回第一个匹配的Item
。
然后现在我们来修改之前的item
查询, 添加一个arguments
参数, 其代码如下:
Field<ItemType>(
"item",
arguments: new QueryArguments(new QueryArgument<StringGraphType> { Name = "barcode" }),
resolve: context =>
{
var barcode = context.GetArgument<string>("barcode");
return new DataSource().GetItemByBarcode(barcode);
}
);
arguments
是一个参数列表,里面可以包含必填参数和选填参数。针对每个参数,我们都需要指定它对应的类型,这里Name
属性是设置了当前参数的名称。
在resolve
参数中, 你可以使用context.GetArgument()
方法获取查询中传递的参数值。
现在我们重新启动项目,并在GraphiQL
中添加如下查询
query {
item (barcode: "123") {
title
sellingPrice
}
}
输出的查询结果
{
"data": {
"item": {
"title": "Headphone",
"sellingPrice": 50
}
}
}
这个结果与我们预想的一样。
但是这时候如果我们不传递barcode
参数
query {
item {
title
sellingPrice
}
}
程序就会报错
{
"data": {
"item": null
},
"errors": [
{
"message": "Error trying to resolve item.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"item"
],
"extensions": {
"code": "INVALID_OPERATION"
}
}
]
}
原因是当前barcode
是一个可空项,程序查询时, First
方法会报错。所以这时候我们可以使用NonNullGraphType
来设置barcode
为一个必填项。
QueryArgument<NonNullGraphType<StringGraphType>> { Name = "barcode" }
这样重新启动项目后,继续使用之前报错的查询,GraphiQL
就会给出校验错误。
变量
现在是时候将参数变成动态了。 我们不希望每次在查询中写死查询条件,我们希望这个查询参数是动态的,这时候我们就需要使用到变量。
首先,这里我们需要确保我们的GraphQL
中间件可以接受参数,所以我们需要在GraphQLRequest
类中添加一个参数变量
public class GraphQLRequest
{
public string Query { get; set; }
public JObject Variables { get; set; }
}
然后我们需要修改GraphQLMiddleware
中间件的InvokeAsync
方法, 在其中添加一行代码设置doc.Inputs
var result = await _executor.ExecuteAsync(doc =>
{
doc.Schema = _schema;
doc.Query = request.Query;
doc.Inputs = request.Variables.ToInputs();
}).ConfigureAwait(false);
现在我们的item
查询已经支持动态参数了,我们可以运行程序,在GraphiQL
中设置如下查询
query($barcode: String!){
item(barcode: $barcode){
title
sellingPrice
}
}
查询中变量是以$开头的, 后面需要加上变量类型,因为之前我们这是了barcode
参数为必填项,所以$barcode
变量我们也要设置成必填。变量的必填设置是在变量类型后添加一个!号。
最后,在GraphiQL
中,你可以使用QUERY VARIABLES面板中输入参数的值。如下图所示,最终结果正确的返回了。
本文源代码:https://github.com/lamondlu/GraphQL_Blogs/tree/master/Part%20V
ASP.NET Core中使用GraphQL - 第五章 字段, 参数, 变量的更多相关文章
- ASP.NET Core中使用GraphQL - 第六章 使用EF Core作为持久化仓储
ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 ASP ...
- ASP.NET Core中使用GraphQL - 第七章 Mutation
ASP.NET Core中使用GraphQL - 目录 ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间 ...
- ASP.NET Core中使用GraphQL - 第四章 GraphiQL
ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 ASP ...
- ASP.NET Core中使用GraphQL - 第三章 依赖注入
ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 SOL ...
- ASP.NET Core 中文文档 第五章 测试(5.2)集成测试
原文: Integration Testing 作者: Steve Smith 翻译: 王健 校对: 孟帅洋(书缘) 集成测试确保应用程序的组件组装在一起时正常工作. ASP.NET Core支持使用 ...
- ASP.NET Core中使用GraphQL - 最终章 Data Loader
ASP.NET Core中使用GraphQL - 目录 ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间 ...
- ASP.NET Core中使用GraphQL - 第八章 在GraphQL中处理一对多关系
ASP.NET Core中使用GraphQL - 目录 ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间 ...
- ASP.NET Core中使用GraphQL - 第九章 在GraphQL中处理多对多关系
ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 ASP ...
- ASP.NET Core中使用GraphQL - 第一章 Hello World
前言 你是否已经厌倦了REST风格的API? 让我们来聊一下GraphQL. GraphQL提供了一种声明式的方式从服务器拉取数据.你可以从GraphQL官网中了解到GraphQL的所有优点.在这一系 ...
随机推荐
- redis基础操作~~数据备份与恢复、数据安全、性能测试、客户端连接、分区
数据备份与恢复 数据备份redis save 命令用于创建当前数据库的备份. redis 127.0.0.1:6379> SAVE OK 该命令将在 redis 安装目录中创建dump.rdb文 ...
- GitHub 系列之「Git 进阶」
1.用户名和邮箱 我们知道我们进行的每一次 commit 都会产生一条 log,这条 log 标记了提交人的姓名与邮箱,以便其他人方便的查看与联系提交人,所以我们在进行提交代码的第一步就是要设置自己的 ...
- Linux下*.tar.gz/.tar.bz2 文件解压缩安装命令
1. .tar.gz压缩命令: 命令格式: tar -zcvf 压缩文件名.tar.gz 被压缩文件名 可先切换到当前目录下.压缩文件名和被压缩文件名都可加入路径. 2. .tar.gz解压缩命令: ...
- 渐进式Web应用(PWA)入门教程(下)
上篇文章我们对渐进式Web应用(PWA)做了一些基本的介绍. 渐进式Web应用(PWA)入门教程(上) 在这一节中,我们将介绍PWA的原理是什么,它是如何开始工作的. 第一步:使用HTTPS 渐进式W ...
- .net中的线程同步基础(搬运自CLR via C#)
线程安全 此类型的所有公共静态(Visual Basic 中为 Shared)成员对多线程操作而言都是安全的.但不保证任何实例成员是线程安全的. 在MSDN上经常会看到这样一句话.表示如果程序中有n个 ...
- Django基础四<二>(OneToMany和 ManyToMany,ModelForm)
上一篇博文是关于setting.py文件数据库的配置以及model与数据库表关系,实现了通过操作BlogUser,把BlogUser的信息存入后台数据库中.实际开发中有许多东西是相互联系的,除了数据的 ...
- Android LayoutInflater源码解析:你真的能正确使用吗?
版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 好久没写博客了,最近忙着换工作,没时间写,工作刚定下来.稍后有时间会写一下换工作经历.接下来进入本篇主题,本来没想写LayoutInflater的 ...
- 『线段树 Segment Tree』
更新了基础部分 更新了\(lazytag\)标记的讲解 线段树 Segment Tree 今天来讲一下经典的线段树. 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间 ...
- 《k8s-1.13版本源码分析》-调度优选
源码分析系列文章已经开源到github,地址如下: github:https://github.com/farmer-hutao/k8s-source-code-analysis gitbook:ht ...
- 在编写Arcgis Engine 过程中对于接口引用和实现过程过产生的感悟
Engine10.2版本 在vs里面新建类GeoMaoAO,并定义接口,在class中定义并实现,如下代码 以平时练习为例,我定义了一个接口,在里面定义了许多的控件,并在类中想要实现这一接口.如果在v ...