|
|
' K Y+ d' }/ k* O8 V5 }* Z<h2 id="系列导航">系列导航</h2>" O- g, e* I- j3 L2 N& F
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
# w, d, [1 e; Y- q0 M- O9 q6 x; v<h2 id="需求">需求</h2>" f1 O( _1 B S* Z! c' ?* ~, o
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>" ^2 N R3 Y4 V+ r6 }' K
<h2 id="思路">思路</h2>5 H/ G% f Q2 o: G
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>, f; f; `( U3 O
<h2 id="实现">实现</h2>; e4 Z1 n8 a% I, b7 i7 e1 u! E+ h) s& S
<p>为了保持简单,我们先定义以下两个类型:</p>% K' ]& f( {7 K
<pre><code class="language-c#">// 定义新增Post的参数
6 g2 H3 g; q8 spublic record AddPostInput(string Title, string Author);2 O9 b) n* K" b- ?: e
! S0 h, z$ d2 F" x4 f! w// 定义新增Post的返回对象( G: D9 w ^* n! Q4 k* U
public record AddPostPayload(Post Post); ?/ \6 M0 u5 d6 V. S' {5 D
</code></pre>
/ C0 I5 l1 i2 u1 v0 h* \! o<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>8 A' K4 Z0 G2 k, k+ X
<ul>+ w: b$ _! m6 x
<li><code>Mutation.cs</code></li>
9 x& H# t, w8 ]2 j3 `+ F</ul>
# B0 Z2 P$ w& z* K- k! \9 Y<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
! u" O" S$ l8 U$ [, ^ ^, l; C8 w
4 ]* s, b) f0 O( j* \public class Mutation$ [) C# v5 Z# d; ^ V" P# d# _
{: C" u" w i- a9 W+ e+ ]
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)* G* K! _" }# \, f
{6 C3 B. q( E' c( a4 [
return new AddPostPayload(await repository.AddAsync(new Post# l) w w# X+ s8 D$ B
{4 G0 l3 P6 M% w# y
Title = input.Title,
6 Q, A$ v( O4 v0 B Author = input.Author* J y3 E& M& _
}));
: f" P7 L. g# Q2 ] }. H. z+ @! d" q+ M! R! }$ v
}
! q% {+ y0 ^& B) t) r
# o7 c: ^ P, o6 D: R9 c" P</code></pre>0 k$ K r# E! ]; b
<p>最后在注入服务的地方进行配置:</p>
* n! k \2 ]7 c7 K) [" ~<ul>
# Q( v9 M6 e6 x# l/ c) s<li><code>ProgramExtensions.cs</code></li>+ ?: u ~6 K% w3 b
</ul>4 c3 f! F1 N5 P. D* M! }" M
<pre><code class="language-c#">builder.Services
$ P% P/ j) \% V* l3 y1 ~ .AddGraphQLServer()
# a# N5 K u9 w! n .SetPagingOptions(new PagingOptions
- e- I* P+ G7 ^: Y1 d* q {
5 k+ f5 }( \) l& S: F' _1 E: _+ D2 p MaxPageSize = 50,
# e5 f/ }) B$ @$ [3 o L1 o IncludeTotalCount = true+ _. O4 c* Q' W; k
})$ |( S1 a$ D4 U" f: e
.AddFiltering()
: k E3 P! m5 V. ^6 C1 R .AddProjections()
# g9 j+ A1 \# V; G% u .AddSorting()
3 }9 `1 i( n1 `9 L" G .AddQueryType<Query>()
3 t& i) o6 T- o2 v' @% O .AddMutationType<Mutation>(); R0 t4 m8 ~; y
.AddMutationConventions(new MutationConventionOptions q' e+ W: J6 E' _# a+ Q) c( r
{( ~% y1 h% u! ]3 V
ApplyToAllMutations = true,
D, K, ~$ Y8 c9 [, J InputArgumentName = "input",
& }7 x& e6 v! M, f+ } InputTypeNamePattern = "{MutationName}Input",
% C0 S( n/ w* n7 M* Q: x PayloadTypeNamePattern = "{MutationName}Payload",1 ~5 S! R% S* J
PayloadErrorTypeNamePattern = "{MutationName}Error",
: r* n) z* S2 k' t7 S' u PayloadErrorsFieldName = "errors"
$ g8 R; L4 u6 w w/ I e; ^+ H })
( ]4 z3 T/ w; A( P4 h8 S .AddType<PostType>();/ L" S8 g: V+ ~: F% P2 B N4 z
</code></pre>
* W; M0 A3 I# P9 v- a% [<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>0 H: h( p1 B. w
<h2 id="验证">验证</h2>0 U2 ` H' I, W0 W
<p>启动<code>Api</code>项目,调用接口:</p>9 y* h6 l4 A! }0 z% ]/ d% m9 ^
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
4 J5 T5 t2 D/ ` k<p>终端的日志输出如下:</p>
' N& }* W% G& x$ W0 B: c<pre><code class="language-bash">[10:45:15 INF] Executed DbCommand (1ms) [Parameters=[@p0='?' (DbType = Guid), @p1='?', @p2='?' (Size = 13), @p3='?', @p4='?' (DbType = DateTime), @p5='?', @p6='?' (DbType = DateTime), @p7='?', @p8='?', @p9='?' (DbType = DateTime), @p10='?' (Size = 30)], CommandType='Text', CommandTimeout='30']
* s: N$ Q# t- PINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
2 K* a d8 {9 D" O4 QVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10); Y5 J% L: q$ s% V" L3 N1 C3 n) Y. Q
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'7 d' D8 u5 k. S$ F6 n& [
</code></pre>
. C( M& `8 A, L) ^3 {' s<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>7 a7 _; e& \ M( J+ {6 @
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>' G3 G8 S( `" |* w) ]5 O' H
<h2 id="总结">总结</h2>( J9 i5 K6 Q+ s ?' p0 W
<p>在本文中我们实现了简单的新增Post操作,这里还有一些涉及到错误处理的内容,我没有在文章中演示,可以参考官方文档 <a href="https://chillicream.com/docs/hotchocolate/defining-a-schema/mutations/#errors">Errors</a>,在自定义异常对象后,有三种方式可以进行错误处理:直接返回异常;使用异常工厂方法;使用构造函数。甚至可以在<code>AggregateExceptions</code>中一次性返回多个异常。基本思路都是通过添加属性<code>[Error(typeof(SomeUserDefinedException))]</code>来实现的。</p>
1 P/ J. f- I/ I2 a<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>8 H0 l4 r9 [; a$ c
$ s6 H; v3 p2 H9 w0 ?0 m' _/ u1 S% V
|
|