|
|
, V6 R& `" c# L# k7 i# q- D, N
<h2 id="系列导航">系列导航</h2>
" u2 ~! ~2 k4 m<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
. ^) l1 t0 S0 r9 U0 t<h2 id="需求">需求</h2>' S+ h( @: V# U7 L- J: X x! N
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
6 J( n% U+ y; n! A5 E<h2 id="思路">思路</h2>( r$ v7 K0 j/ ~ [' A9 c J& i) `
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
/ q) b& v5 L& ?/ Q7 h# t M<h2 id="实现">实现</h2>
" ~4 @- D( o2 j<p>为了保持简单,我们先定义以下两个类型:</p>
- W9 f& V- U4 q. \2 Z! L( t<pre><code class="language-c#">// 定义新增Post的参数
1 q$ O1 i5 N6 N9 ypublic record AddPostInput(string Title, string Author);
. ]: ^) I. R# a) z, g( E; D8 L
y) ] b1 I5 O" Y' \; P+ \( G// 定义新增Post的返回对象1 C# K# C6 ]7 w
public record AddPostPayload(Post Post);' _' H) L. ?- Y0 Q6 F
</code></pre>
8 H. C2 W" w$ L3 @3 p. G<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>5 K6 X/ r" `! Q4 T/ q0 b
<ul>
4 d' }" X5 Y/ Y2 M& r7 `<li><code>Mutation.cs</code></li>
2 E5 @6 l: z/ U! ~& B2 }" f% p</ul>7 x! C, f4 L% a) i
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;6 G4 F, s, u3 T% ^ F* B* a
9 {/ @( b9 @/ O! v+ k: Q& @% @public class Mutation. K6 y. \: G J5 C g
{4 f' x8 r' P. y3 z% D. N& i: C
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)& r+ U- |9 C, G/ ~
{+ L! P; A; w/ h2 @2 C
return new AddPostPayload(await repository.AddAsync(new Post9 \1 `% s. F3 T0 c
{5 t9 Q9 g1 O3 n0 c$ I( ~
Title = input.Title,$ K: {) g; W5 p# C
Author = input.Author
- S. K' s/ Q. z& k- a9 K q }));
9 o3 _' K, {' d }. `6 f& x, c' h8 J4 v9 h* b% s
}, _: {! g a# D+ g: x# M
4 s4 y/ L7 R5 ^- Z8 k
</code></pre>
+ O1 q2 J2 ?. I$ l. \<p>最后在注入服务的地方进行配置:</p>
0 [7 N$ Z' Z) K) a: M; _7 d' {<ul>
: T3 Y- E, t7 G/ R/ V. u; @3 o<li><code>ProgramExtensions.cs</code></li>+ l7 m* O3 R1 b2 D Y1 d
</ul>* z V9 y8 K) j4 x$ E
<pre><code class="language-c#">builder.Services
q' r' x! s. a7 ^- R0 ]7 r) D5 [9 ` .AddGraphQLServer()
) W# _1 m; R: y7 y& Y$ p .SetPagingOptions(new PagingOptions
; D9 K' E' n, U: y% A- a: W/ I8 \ {
- I& q4 I8 G: O$ u MaxPageSize = 50,0 t! f9 ]4 A0 Z9 c
IncludeTotalCount = true
4 e: n5 s) C2 \6 P: r' _/ ^ })# F* v W6 v" a: _- F( |% a4 |* d5 u
.AddFiltering()
1 x! |; ?# ^+ S2 ? .AddProjections()6 V* R' H8 j& B7 a9 |
.AddSorting()
1 \( Y) v0 A2 M4 D9 S9 R: v .AddQueryType<Query>()+ i7 D% ^/ n0 h, |
.AddMutationType<Mutation>()
( I* f, U! |& k' D; D8 ~6 H; @ .AddMutationConventions(new MutationConventionOptions
, |* {3 N7 y8 q$ }* S+ T {8 i" N* G3 _( P) ], b
ApplyToAllMutations = true,1 H+ t# \7 S& G- l, w
InputArgumentName = "input",
a1 F3 y: b4 z6 V! a/ K& |+ V InputTypeNamePattern = "{MutationName}Input",/ D" e$ F3 r# N9 O3 K
PayloadTypeNamePattern = "{MutationName}Payload",1 s5 F/ y4 S& j: t6 @* d
PayloadErrorTypeNamePattern = "{MutationName}Error",1 R1 B. A& g2 |! O& f
PayloadErrorsFieldName = "errors"2 K$ ?; n+ L+ \4 A" @
})
! ~1 [) }9 h' f3 r j- X9 z# j1 u .AddType<PostType>();# O) G& Z9 q. h5 {" o3 s
</code></pre>% b" Y- N# I/ @- F* ]+ _
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
8 y3 a& L5 B. v A# E( _3 K4 L<h2 id="验证">验证</h2>$ f8 x+ V# ?3 s; [' ^7 T- j/ V
<p>启动<code>Api</code>项目,调用接口:</p> T. |5 a* w1 _# u% Y
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>% C' l$ l* _: o& b) U& L$ d: ^
<p>终端的日志输出如下:</p>2 ]+ `# w& i7 k: ?* B5 L% 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']
/ c' L& m7 U/ EINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")1 R, ~+ X5 X0 w0 O2 G" B% g8 q
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);$ Y' U/ A( B- B8 H
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'( B p( B8 g& J. ]7 f
</code></pre>
( f0 K2 Z/ n" s- D0 J" o5 K w9 ~<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
6 b- H) K4 V' f2 k9 N* |: O<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>) U* F, e' F+ P5 O) D" M0 u+ k/ p
<h2 id="总结">总结</h2>. Q% X _+ m+ U& F* T9 L+ J8 l
<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>: ^6 G1 h6 I9 q6 F7 g8 s% ~9 x
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>4 X' V" j( H6 z! c+ J1 q* y
. A k, P; \% u' z. p7 H5 s3 X4 E6 Z
|
|