|
|
0 J( B4 o$ D/ _% ~! [- u& k" j- D
<h2 id="系列导航">系列导航</h2>
; C4 p3 \" U8 a<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>0 `! `. Y' \9 U6 D) Q
<h2 id="需求">需求</h2>: v8 |% ?! f: O( Y: O
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>) Z9 r* @2 S: z4 g5 x: B
<h2 id="思路">思路</h2>
. E( I2 A$ A; l# M7 b2 N<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>+ {. D5 Q6 s9 o0 c/ I0 d
<h2 id="实现">实现</h2>7 f+ D+ _/ t- d+ K2 m& I% [
<p>为了保持简单,我们先定义以下两个类型:</p>
$ r4 D5 Y0 \3 U7 _- b) C3 ^5 }3 |<pre><code class="language-c#">// 定义新增Post的参数
; _+ i. o9 {0 D! q" m! ~public record AddPostInput(string Title, string Author);
/ d- x- }: \3 Y x' u( D+ j, ^" o$ E8 j, E
// 定义新增Post的返回对象6 v6 h* }' }4 \& I+ d
public record AddPostPayload(Post Post);% I9 q! X; r7 U4 W e* S! k' ]
</code></pre>9 ]0 `% W$ K t1 w# e' D( y' v! u
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
; C2 Z3 A: V3 Z9 R, v4 D3 r* _. ~<ul>
" p; a; V; v/ Z: N4 ^<li><code>Mutation.cs</code></li>7 G! ]' S$ }" C( D: x$ f
</ul>3 V$ F) S( D0 b( c0 {
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
7 N' w3 |& S9 y* m
1 |7 [" |' _7 Q$ T3 `6 h3 t& hpublic class Mutation1 N8 m$ F, N8 j% L% z
{3 }% S2 C X- M
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository); Q0 [" V: |, \* {( N
{
# _* a. M3 B/ I5 t, E# l" l. Z return new AddPostPayload(await repository.AddAsync(new Post
3 b% v3 X# {/ r- S {6 @3 v0 ?1 U7 N2 a A1 ^9 h
Title = input.Title,
* L( Z% f& ^" ?+ l& y7 i Author = input.Author
" \! U7 m' N0 r" }2 ^8 _5 \ }));
4 o, Q$ E2 T2 W- C2 @3 J }$ q }* U, d" p1 h+ }4 f; K
}
; n; z- h6 w3 x1 g7 k
$ [( ^" v, i+ u2 Q! l</code></pre>/ w. `' g3 ^! d/ \, _1 T. D% n
<p>最后在注入服务的地方进行配置:</p>, b* o1 e+ G8 b+ m5 w
<ul>
" {4 _% N; `: F2 `- r- L9 t$ F* t<li><code>ProgramExtensions.cs</code></li>
: { V1 x* O/ T: @</ul>, U8 x' F0 p7 M7 ]. b! X
<pre><code class="language-c#">builder.Services
! ?. O$ D/ Z3 `4 \ .AddGraphQLServer()7 p( @; w0 R) h, A
.SetPagingOptions(new PagingOptions
. `0 I& p5 P& ? {
. ], W0 q8 ]$ E1 e- g MaxPageSize = 50,2 U7 _2 ]2 N* D7 p/ D
IncludeTotalCount = true
% J( l$ A) }6 ] })# ~$ X* @: u! z) I) v2 A
.AddFiltering()
% d' B: @% Z1 i( {0 a# G .AddProjections()
1 H' y/ d! q5 K+ k3 u: D0 F .AddSorting()
U w7 W% V+ o: t/ Q# p9 ` .AddQueryType<Query>()# q' d- i, X2 N# q4 h. p
.AddMutationType<Mutation>()# o. [: X5 G2 [8 p( ]
.AddMutationConventions(new MutationConventionOptions& D3 Q) g% u1 x; [& M
{9 ~% Y' ]$ r, }7 L
ApplyToAllMutations = true,2 D+ V, G; v: j5 O8 N, a
InputArgumentName = "input",
1 B# T& ^% C. E4 V InputTypeNamePattern = "{MutationName}Input",7 G) c' S; L/ G# g/ N0 q
PayloadTypeNamePattern = "{MutationName}Payload",& ~ @4 @* e2 G( o- p+ g1 L
PayloadErrorTypeNamePattern = "{MutationName}Error",
. L# Y( p/ w) s; v- m PayloadErrorsFieldName = "errors"# o, r/ w3 E. G$ ^ x: O4 p7 D0 I
})
# M/ @0 q- v( n! m1 m .AddType<PostType>();+ m; ~ }, @6 G8 @2 |7 g
</code></pre>
9 H$ h, @$ Q2 }<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
& \6 B6 p" o4 ?7 V<h2 id="验证">验证</h2>1 a$ H4 Y( Q8 y W U! v6 h8 i1 \
<p>启动<code>Api</code>项目,调用接口:</p>
1 m0 F- D2 }6 i3 o5 T% Q* E; u<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
* q9 e! Y ^: x6 z<p>终端的日志输出如下:</p>
+ g; h, O8 {8 S% p2 ]! @. t$ \<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']
`& P$ S) S, g% A/ XINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
" V% r% e1 Y1 zVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);1 T' V( I% p6 ?0 I2 P3 m* y1 g
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'! O! v+ V$ M+ Y4 y: [0 e8 P
</code></pre>
% l1 c% t" x% r Z<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>* h, Y1 ?! h7 y) O
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
+ k0 y0 n; Z k v4 X ?( C1 y<h2 id="总结">总结</h2>
& m [$ [+ M1 f<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>2 B+ @) n! Y8 Q+ i, b8 }" P* G
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
$ g& s* k% v4 O8 R. u }( C& o
J; c% d1 P- v7 W2 W3 ` |
|