|
|
3 R7 Z/ a5 e" Z6 R<h2 id="系列导航">系列导航</h2>
, I* y! k: U( S* w u' G<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
. P+ P/ U1 N. a) x, c9 p<h2 id="需求">需求</h2>7 ?, q8 M( {2 m3 j+ m
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>& l1 o6 s) }/ e h3 L
<h2 id="思路">思路</h2>/ l/ d7 I1 g( E8 ]* ^
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>6 Z6 G6 @; _- \$ w' c8 _, W
<h2 id="实现">实现</h2>
, w6 s0 i6 K0 @; P d- }2 D) c# S! g<p>为了保持简单,我们先定义以下两个类型:</p>1 C i+ ~7 @- H$ Z: f( c% N% A
<pre><code class="language-c#">// 定义新增Post的参数0 i1 q$ q) Y4 q. D/ W
public record AddPostInput(string Title, string Author);
/ \. r% l3 }3 f! J5 z. C J7 o& J% o( Y8 I
// 定义新增Post的返回对象/ ^& M3 G; B, R' z6 F( y0 ]: n
public record AddPostPayload(Post Post);! I5 W9 l/ A% L B8 p* w
</code></pre>
% S" o& f/ N" i* f. r9 R% |<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
, c) ~- k$ M1 }<ul> ]. j7 ]$ W( s3 _* |
<li><code>Mutation.cs</code></li>
; g% C7 W) d8 W; f2 j</ul>
0 a y# V5 d$ w5 \3 t+ ] Z0 D<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;. b, `; G8 \7 D* C
! ~% P" ^$ j" i" v; p
public class Mutation/ Y' t% l3 z2 V4 z
{
, u' ]7 O2 Q" _7 |" r) v public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)% D* G* ]7 q7 f5 N; }
{% l4 T' s d2 Z% \) j' H2 P
return new AddPostPayload(await repository.AddAsync(new Post- q6 o, V8 o0 K) Q8 ]) w" O1 v
{
5 R1 z7 b: D5 q- Q# c! A Title = input.Title, g7 C" r: a+ G& c; n# g
Author = input.Author g' d) {- b* M- J7 x* V
}));3 T& H; J. ]8 M @; M
}
6 R% M, D% m" J9 X) a. M3 O( D I; ] b}
- ]8 I- N) q- J
0 E7 I; n- T9 ?# h+ Y8 q" d+ v5 O</code></pre>
5 v! N+ T% u8 } O- Z! L2 `, U<p>最后在注入服务的地方进行配置:</p>
% `% b( J2 @3 e1 S<ul>
6 X: P$ Y3 a+ E% J* D# r<li><code>ProgramExtensions.cs</code></li>4 U+ c# x, \& ^* M- G s
</ul>
- o+ v7 B; _4 D; w; d$ c<pre><code class="language-c#">builder.Services
0 `" f7 B# b+ {: T7 W .AddGraphQLServer()
- _: j2 _* L8 M .SetPagingOptions(new PagingOptions
/ X/ b5 C" b2 g7 E4 G. m% E {
3 K0 p% ~" F# p/ f. i% i MaxPageSize = 50,5 c E9 p; b* |
IncludeTotalCount = true
+ y; u# ~- o8 e })& O5 E0 X1 f6 J- A! v
.AddFiltering()
' K, m! F' l! I7 G .AddProjections()
- B7 b4 x, @* U6 o% L6 m2 ?4 X .AddSorting()
2 B4 t2 i! j* k6 U .AddQueryType<Query>() E, L. E. ?* Q$ \& U8 N
.AddMutationType<Mutation>()0 \' c8 r* L" Z. C' B
.AddMutationConventions(new MutationConventionOptions
( z* ]1 h0 |" u7 p" s# v7 U {9 ?" g; u# d8 z
ApplyToAllMutations = true,
" x+ |3 D* W4 s. w Y* v# @( K3 y5 w InputArgumentName = "input",1 f' e; }& j, v! O+ J
InputTypeNamePattern = "{MutationName}Input",
5 m- g* d/ l# L" q PayloadTypeNamePattern = "{MutationName}Payload",
) g1 b9 {7 ^0 B6 D5 t1 ? PayloadErrorTypeNamePattern = "{MutationName}Error",
9 z# C! Y- D$ K# Y+ x PayloadErrorsFieldName = "errors"$ V9 d2 _1 Q$ c
})
" X) f) F* B' o6 C3 G# _& _ .AddType<PostType>();
- _3 Z: m8 N7 A! O</code></pre>
2 C+ _& G) m3 }3 l<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>$ x* m) L- P8 R' D4 l
<h2 id="验证">验证</h2>* G Y9 ^% ^( E% b9 i3 E) D; N
<p>启动<code>Api</code>项目,调用接口:</p>" Z: }$ n& P. ^! Z/ N
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
1 ^ _7 j/ U) \# e( z9 w0 P/ ^' z<p>终端的日志输出如下:</p>- u; e+ V4 |; f7 @6 ?6 ]
<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']' C0 \6 d" O! g+ ~0 O+ F) D
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")* V+ H4 M3 R% g4 U7 u/ Z
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
% ~1 H: y! }2 b/ n p' ~- l7 y$ r[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
. H) @/ ^/ s" _# W- D8 r</code></pre>7 d$ I/ ~$ \8 x5 F
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>0 o; C1 b- j& I, U3 \
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
4 D. e* y H3 D: y<h2 id="总结">总结</h2>9 o7 P+ f: Q4 X1 {/ [( a, _7 Z1 x- E
<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>
! F) J, ^- G$ O. n6 y: _; j' @<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>1 @" I+ m$ L! H2 l
. K1 q" T8 l7 y5 {" i* ~
|
|