|  | 
 
| . g8 b- a$ l0 s1 p<h2 id="系列导航">系列导航</h2>" g& R* w' M( N- P
 <p><a  href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
 : ^! ~) O$ \& w: D% H<h2 id="需求">需求</h2>+ e- T! E# ?5 x3 y* P
 <p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>0 ^8 S/ |8 W+ G0 M9 W- W; x3 z
 <h2 id="思路">思路</h2>3 r5 ^# B: J4 W* U( `
 <p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>! _" X  j* V' o& m
 <h2 id="实现">实现</h2>' q9 Q" `8 J1 }
 <p>为了保持简单,我们先定义以下两个类型:</p>
 7 M7 ~; q# L5 b$ S<pre><code class="language-c#">// 定义新增Post的参数
 - ~+ n" e: B( F$ X8 n  Z5 ?7 ~public record AddPostInput(string Title, string Author);' U2 W$ r9 l% {* X; M- }' V
 
 ' ^1 D7 v3 p, ~# _& t/ e( _// 定义新增Post的返回对象
 8 `3 ^( f. j3 F# r# K. e. tpublic record AddPostPayload(Post Post);
 ) l# ~! n4 a5 g5 U</code></pre>
 , [4 W0 L( `8 ^7 k1 U. C7 |<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>1 Z& ^! e/ b  b) V; _) }
 <ul>( g% E4 x5 Q% J) v& S7 _; O) n
 <li><code>Mutation.cs</code></li>
 4 g# d( U4 q% u* ~' J/ d</ul>
 ! z5 \1 l8 G6 `  I. {+ `- z<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;% r: K0 W* o8 q: p6 b4 {
 " d, R5 k2 g2 ?( L6 z
 public class Mutation
 : ^3 b: O) Q3 Y8 z& t6 ^) Q- I1 z3 {{( a0 v$ r3 n  f6 s
 public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)3 [, X( Q. Y" T# |8 [+ ~5 i3 U
 {) K0 Q0 d3 E+ B! v4 G
 return new AddPostPayload(await repository.AddAsync(new Post
 ; q1 m5 I7 x( ~( H8 e4 c9 ~        {
 0 J9 J5 B) [# O6 O            Title = input.Title,# e# x7 K8 v7 c) p5 r5 N7 Y
 Author = input.Author: u9 g7 R% p6 Q
 }));
 # `3 P2 O0 `9 ?) H' T, l; V8 ^% [    }' c$ c% [+ f; C$ [
 }$ e4 t- b5 R( ^2 {/ T/ W6 l% s
 3 h$ ?7 D$ L0 ^) V  X: m
 </code></pre>1 z' R, O. e9 `7 b1 j0 O$ z
 <p>最后在注入服务的地方进行配置:</p>
 ) \( A0 f1 x1 k- M8 i<ul>
 / F3 ]( w/ F; M* G# \' _<li><code>ProgramExtensions.cs</code></li>
 . ~8 x  O3 |# F) T& I</ul>8 X& x" ~+ x* u) d% f
 <pre><code class="language-c#">builder.Services- ]4 W" _# G* t1 T9 |
 .AddGraphQLServer()
 * {: V7 ]; }1 j. G9 U: i6 \" T    .SetPagingOptions(new PagingOptions
 , L9 `3 L( @9 I* Q+ Z) i. D5 `6 Z    {. }& E* M1 n" p* C! }8 g5 l( d
 MaxPageSize = 50,9 U4 _! N0 Y( P4 O: i% ]9 ~; d/ s7 Y
 IncludeTotalCount = true
 / E, M. o& u3 @    })
 ( J# e- z3 R- E' j    .AddFiltering()
 % B9 B- l/ _2 G2 I0 T    .AddProjections()6 }' L# w3 [  @% b9 V+ @1 V) I) |2 X
 .AddSorting()  _3 n* z2 j  a- Y6 z% S
 .AddQueryType<Query>()
 * S; L: X% U5 R: K( X/ D    .AddMutationType<Mutation>()
 . V3 W! b% F" w+ @  o1 }    .AddMutationConventions(new MutationConventionOptions8 j1 v1 X$ T2 e/ F0 m2 {6 k% p) t) j- N
 {
 # l4 Q7 W. m$ p" ?        ApplyToAllMutations = true,, U$ `, A2 X, W; P7 E' o
 InputArgumentName = "input",. l( m! ~4 @, d' j
 InputTypeNamePattern = "{MutationName}Input",# T- K; I; K; w5 W5 g, _
 PayloadTypeNamePattern = "{MutationName}Payload",
 . t7 E6 M& _8 L; d        PayloadErrorTypeNamePattern = "{MutationName}Error",/ F! d, \4 n; H7 \2 G" \
 PayloadErrorsFieldName = "errors"0 R; [5 u3 L/ P; z
 })( s. }4 l' D: X
 .AddType<PostType>();
 : O* J' X. m! U/ P1 B: |3 {  L</code></pre>5 F; G9 r6 h8 G2 U7 ^0 f
 <p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
 6 C! F' `( c* a0 e( H* K  {<h2 id="验证">验证</h2>$ D3 v# n2 Z+ g$ d
 <p>启动<code>Api</code>项目,调用接口:</p>
 ; P3 ?  w3 W7 s& N2 {. z8 Y& R<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>5 F0 ]$ d; K5 b% q) w# ~; j' a  \
 <p>终端的日志输出如下:</p>
 7 y7 ^1 P' {# e# c2 K6 K<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']0 _0 c3 h, e2 O  I# Z
 INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
 # h% t1 a# }8 _VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
 $ A; ~8 e  x& ], y7 P# S[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
 8 A, W! N% {) D4 i* Y9 F5 \$ T</code></pre>- p9 H1 C% C& }4 M' V! l
 <p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>) H5 X4 I0 h% `! n! x9 s
 <p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>( U% N5 l* ?3 B) g: y
 <h2 id="总结">总结</h2>$ W7 L4 E+ q9 m: K- a  A
 <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>+ ]7 ^  B. k/ R  O  H% l
 <p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
 - I/ T7 E( j. ^* w
 e6 r6 ]' V' V3 S
 | 
 |