|
|
8 J: N% q P4 v/ E8 }7 I<h2 id="系列导航">系列导航</h2>" A, Z; A" b: O; G
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
4 s& X* H' x; W<h2 id="需求">需求</h2>
0 M ^4 t: _2 o J# m f: k<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
2 u2 N7 D7 ?, G1 \* h$ m! h) {8 C<h2 id="思路">思路</h2>
) [ }: F1 v9 f6 _$ g0 Y& u7 K<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
: q: H" `. M( P6 d& M i6 C<h2 id="实现">实现</h2>
' i" Z1 Y! W0 E<p>为了保持简单,我们先定义以下两个类型:</p>! x. X7 L l; f
<pre><code class="language-c#">// 定义新增Post的参数* \# L, c( e1 I7 x- k# k- [3 a
public record AddPostInput(string Title, string Author);! w! M& ^* \( Z: s
; d. R6 q% ^3 `' [$ r! |, z// 定义新增Post的返回对象
8 N4 e% C8 ]# c3 ]& T, f& ?public record AddPostPayload(Post Post);
b- \0 [+ U* b7 O+ a# q; q</code></pre>$ Z# L9 N/ e. j; M
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>5 s: `+ o. ]5 J4 ?9 V. J: B+ C5 s, e7 Q
<ul>
( P/ l/ R1 c: D, Z X: c3 d: [<li><code>Mutation.cs</code></li>! s0 g' y- M" g% ]5 ~* H
</ul>$ ~/ v! Z. Z3 |, _) N
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;/ l z$ S6 ~+ Y2 L M5 M# q0 e" @
+ C) x5 g3 b$ I" T0 i8 i) \; @% ~4 z4 `public class Mutation
9 _8 P: J: j+ R! x{5 f& l: C8 K9 j7 h N$ s
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
8 L% M9 }" ], h" t' R6 a {. h6 W9 S: e( z) Y
return new AddPostPayload(await repository.AddAsync(new Post
* d5 E3 a, |+ x0 F4 T1 N- ^/ X5 S. \ {9 U( w6 L3 h7 G: \
Title = input.Title,- P' ^4 _- p+ s8 F7 D
Author = input.Author
* [# h9 c9 C+ h% B+ a }));
3 \% G, U6 [$ s5 Z; y }
9 X3 Y/ K5 V' m9 f8 S0 F}5 `, ^7 Z$ q3 s0 O" E9 e
5 ?* v$ o$ r% q4 [+ D</code></pre>
8 t8 w1 r0 `" l$ H1 X<p>最后在注入服务的地方进行配置:</p>& I2 s( ]9 R+ W/ B, v3 p) V
<ul>
& r0 v% p4 @7 g% A( _<li><code>ProgramExtensions.cs</code></li>- o) X, c, @9 D& O) N
</ul>
, b( u7 n' K4 D<pre><code class="language-c#">builder.Services5 r# q9 s$ }8 x4 U6 P5 O
.AddGraphQLServer()2 q' Q( N1 z5 W& D' X
.SetPagingOptions(new PagingOptions$ N1 P# z0 o+ [* n
{3 y9 p( Z. e$ G
MaxPageSize = 50,+ u' ?, w% {, d+ X w9 ~
IncludeTotalCount = true1 n6 G) w; i9 X9 n; a4 C6 V6 b$ T
})5 k: l& P; W' R" k
.AddFiltering()
0 d; B u* c0 Z .AddProjections()
% ^5 o4 c# c7 A- L$ X4 J7 q0 s .AddSorting()
3 T, N3 f& [" l- N' { .AddQueryType<Query>()
% l3 ?% P2 Q: x% @1 _! w .AddMutationType<Mutation>()+ \: m) `3 h. f& }* X* n& E# Y
.AddMutationConventions(new MutationConventionOptions
3 U$ Z3 \9 s$ o$ C9 r) x% ] {
: N: D" x @6 w3 X ApplyToAllMutations = true,1 g( Y! w% J; N8 w% W
InputArgumentName = "input",
& Q& S$ Z! l$ ?7 i1 w- W InputTypeNamePattern = "{MutationName}Input",
! e5 g+ y; w# T: o PayloadTypeNamePattern = "{MutationName}Payload",. n; `3 l8 ~" w7 _, Z" T/ v. ]
PayloadErrorTypeNamePattern = "{MutationName}Error",9 @# S1 N4 r; J9 w5 S; @! z
PayloadErrorsFieldName = "errors"
- h* A4 T9 J- |. Y) f })0 c A$ H# k" x7 t
.AddType<PostType>();, u( k6 v% X( y# U2 I5 H$ i
</code></pre>
9 N; {+ j4 Z; q* F<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
/ d3 B( i; ^* A<h2 id="验证">验证</h2>
+ d" |* k( M6 F, o1 o( r5 K<p>启动<code>Api</code>项目,调用接口:</p>- |: ?* t- _; t0 {% l8 E
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>- [ }& V4 B/ s4 s |4 y0 }/ [
<p>终端的日志输出如下:</p>4 h, ]; x& E+ m; D
<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']* B0 j4 } M4 P
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
8 ?8 O5 ^) Q: f8 |8 W2 n, iVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);2 ?, X3 x: i! Q4 C6 |4 _. q
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
+ m+ a+ {5 |0 C s</code></pre>+ k) g4 S/ \/ r( C& `. [
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>1 s+ W8 j R( ?& M* R
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
/ N9 m5 i5 X- w( `, ~: e6 o( z/ H<h2 id="总结">总结</h2>
" I6 @/ r6 i U<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>% q5 \! |+ B+ a7 j
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
0 C/ h# Y3 G7 g
2 s* m7 W$ B& v( a/ ]* @) S. g |
|