|
4 G7 w$ e) \1 V" A- p<h2 id="系列导航">系列导航</h2>
2 {; B" o: h2 v$ J' H<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>- H. _+ {9 Z- U7 s$ k# d
<h2 id="需求">需求</h2>; [5 g; J! T0 o3 P- d
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
. B1 T. H/ k& V$ Q/ D- y' w<h2 id="思路">思路</h2>
+ U8 `- J0 s# U6 c$ I<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
+ v8 { v! ?) I" z/ @1 H2 [<h2 id="实现">实现</h2>
' D# O2 W, h% a" l# z1 E! z+ n<p>为了保持简单,我们先定义以下两个类型:</p>3 E7 b) |6 [/ y8 L) w3 j
<pre><code class="language-c#">// 定义新增Post的参数& O3 b8 p% k" W- ^$ s
public record AddPostInput(string Title, string Author);
. G' F9 A/ C, U' u3 Q% v) R8 o* h
// 定义新增Post的返回对象
( w. x5 B/ R/ u# p, _public record AddPostPayload(Post Post);
1 J% Z/ P- A6 C) W</code></pre>, O, E5 {0 |4 S. b$ p+ v# K7 y* C
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>8 \7 s. q' ^; A% L$ \
<ul>- t6 l. e7 u* {1 f: z7 N- B* ~
<li><code>Mutation.cs</code></li>1 W- f6 T9 f! a5 \7 y: S, Z
</ul>7 E/ h; N' Y* P* z+ n" I' Z
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;" ?) O V9 c! F- e" @6 _
/ R& r% a3 b& o) \# o. X
public class Mutation; ?. N/ I- y0 W9 ]) _9 B* ]
{5 t. X3 P3 Q( _- I2 d5 I
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)( f2 j* H' |. c& ~& L
{
) x8 O7 G: A" K: h n return new AddPostPayload(await repository.AddAsync(new Post
: A2 m; X2 f% }( J {9 k/ M3 c' A# X; e8 A( x+ k
Title = input.Title,$ ^. p/ @9 P+ w( S3 ?7 L
Author = input.Author9 O+ T3 b/ X1 @& B, z4 N Q; j7 x; h
}));! c; j- }+ ^2 S; A1 g
}6 T( y3 j% ^% A( u! y! S+ B* Q1 ?
}
' u& W0 j2 n% U2 f
, q. Y, N( M m: J# W% ? {6 E</code></pre>3 n/ r) Y! ?; Q4 B+ t1 X* x
<p>最后在注入服务的地方进行配置:</p>
$ y" P2 Q P: T' ]7 R4 z6 |4 Y<ul>
4 M; x& ^) I6 l7 w$ |# f! r( ^<li><code>ProgramExtensions.cs</code></li>
1 f6 l" M* B1 C4 k7 M% w- ?</ul>
; u- u9 U; Z& y' ]- z/ Q<pre><code class="language-c#">builder.Services
# W+ e, T( m3 u, n1 O0 Y/ Y .AddGraphQLServer()
+ G% j6 _# x( b1 a1 S. K1 o .SetPagingOptions(new PagingOptions
! F( e9 R+ l9 l/ |9 X& ]0 w {
: \- r* g2 }. D/ R9 A" y MaxPageSize = 50,
5 F, X/ K" c4 w/ P& \8 D+ I; A IncludeTotalCount = true, ^4 W7 h2 F- G& v/ z/ X
}): u# x5 f; t- F4 g
.AddFiltering(), M: s5 B0 K8 a8 @4 w0 v5 X3 k
.AddProjections()/ B4 C' t( x$ P% ^: g
.AddSorting()
* o) t" M) n& b" h0 W/ i .AddQueryType<Query>()7 ?3 {- V2 m& p9 g; g+ t
.AddMutationType<Mutation>(), R& M# a, s: j) v2 t+ T
.AddMutationConventions(new MutationConventionOptions3 K9 }" a( g" c- U6 U0 K/ B
{
( J2 s- v7 E" A0 r- G: Q% N ApplyToAllMutations = true,
' z. w# I: C7 o! e InputArgumentName = "input",: D2 ~; O V6 O8 u" N5 p( x
InputTypeNamePattern = "{MutationName}Input",0 @) f! C$ `/ x- L9 O
PayloadTypeNamePattern = "{MutationName}Payload",; e) r* {' y$ U( D3 a: m$ C
PayloadErrorTypeNamePattern = "{MutationName}Error",
G4 }" `) U }! o- ` PayloadErrorsFieldName = "errors"# D7 K, l: p- @/ h
})5 D, R1 |( ]; Z" E
.AddType<PostType>();4 W3 H% ]/ h: n2 F( k* w
</code></pre>5 M" }. W q0 J. Z i% X( ]3 T: U2 t
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
4 Z) Q' i$ y0 H1 L<h2 id="验证">验证</h2>
$ t0 [7 k3 P" A, c7 O6 d5 ^<p>启动<code>Api</code>项目,调用接口:</p>
( {$ X6 C# \; I. f; c' X<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
" U; J' n6 y: R; P<p>终端的日志输出如下:</p>
& l& g2 @; L& z; z<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']
* w2 R7 K o: A: E: b% ^INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")) l' l6 x( ]/ u+ _7 Z7 X
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);0 M* T/ D- T" i' ]% ]
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
7 V4 w, ?, `2 w8 n: }</code></pre>: v1 S% d1 y; O" R; m) {* p
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>9 r! I) `$ p/ m5 _! x! ]
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p> L! ?7 D- u( E1 S6 h) ~# I' h0 [
<h2 id="总结">总结</h2>
# p3 i% _1 K: x" x" G3 Z<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>' w6 B2 z; W, U( i% u- C0 h* R
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>0 [3 t8 C e3 H3 [& m0 i. @3 B
# d3 i2 P& S6 G0 H
|
|