|
|
- t( S' e" U$ M6 h- o5 `9 G! o/ P8 S- r
<h2 id="系列导航">系列导航</h2>
4 W5 J) C7 A* s/ a<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
4 J1 F6 @: q, X' e<h2 id="需求">需求</h2>" a/ i$ k: D) H
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>1 \0 S/ H% u! n1 E$ J
<h2 id="思路">思路</h2>) i& _2 Z6 m) a5 o1 k
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
- D# c4 C" m! Q& V( L- w+ `<h2 id="实现">实现</h2>
& ~( A8 g0 Q( V1 |) P<p>为了保持简单,我们先定义以下两个类型:</p>
! \# [" @7 r3 T<pre><code class="language-c#">// 定义新增Post的参数3 W5 L) b( |* n" r! e/ J
public record AddPostInput(string Title, string Author);
2 g7 _- Q2 K1 x6 Q4 d% S
6 h% P* E$ t5 M2 o! ]. n// 定义新增Post的返回对象
) T+ R8 L) u9 F: `0 H$ m A: @8 apublic record AddPostPayload(Post Post);' ?$ P6 B/ ^( Q4 J0 s/ B9 ~2 ~2 y0 Q
</code></pre>
( U d3 p# U4 W3 t3 O% `6 T6 S) {<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
/ Z0 f9 y+ R' [2 `8 n. e+ j* I3 |<ul>' U" M; u5 z9 ~3 E6 V, a# e
<li><code>Mutation.cs</code></li>
3 }2 I( ]: `& x/ v) V: o</ul>
( Q/ ?. { e# _+ x<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
% B! K+ f: f2 ~7 X6 c, l" w# h J! _8 u- e/ b0 C
public class Mutation: v A+ F8 Z ^2 _2 |, K% H
{
O/ S# Q* A* P9 ?$ k! V public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)* C* `$ b- s: I; P5 z, ^
{
$ e/ l& P- F6 U# E. N5 M return new AddPostPayload(await repository.AddAsync(new Post+ l) ?! y& J$ N
{
" v5 `/ K/ a+ P H5 Q Title = input.Title,1 ^0 X9 E; h3 I# y }! i
Author = input.Author& P) y2 l1 | v2 a
}));9 w4 K5 l( F) W
}$ _7 g- u$ U/ U2 U
}
9 l, d2 K ]/ h8 ^0 e2 f$ v) s4 S3 U( {- M& q
</code></pre>
n: M6 }$ t& W) n0 J! r6 c% k<p>最后在注入服务的地方进行配置:</p>' m; I) o! K- v# z
<ul>5 ]. X: \6 e+ @0 w \; J
<li><code>ProgramExtensions.cs</code></li>
: R. r+ x m; l</ul>
& C! l7 K a4 H# Z" v<pre><code class="language-c#">builder.Services6 |3 u, C+ W- [$ T( K
.AddGraphQLServer()
( v, {: L( |1 |8 F# g .SetPagingOptions(new PagingOptions4 u" G7 Z2 V( d0 j; W/ C
{- W) Q, T) c) a$ R5 D( j
MaxPageSize = 50,: K: M7 d% E) @8 g
IncludeTotalCount = true& d2 U e7 \& m i/ w2 T
})* A* a- |! E6 v* p( b. l9 ?
.AddFiltering()
! t4 H4 e# a3 W9 x9 _2 f2 v .AddProjections()0 G3 E) I; t C, X
.AddSorting()
( A2 l7 R! ~6 R. M. W$ Z .AddQueryType<Query>()" y5 J+ e1 L5 e8 d' I
.AddMutationType<Mutation>()
k# j3 I) @: b8 Y K .AddMutationConventions(new MutationConventionOptions* K. \- G) q+ Z6 c3 F/ r* u. T
{% N: `( G. J K! E: g0 J
ApplyToAllMutations = true,
' |8 h, E1 R2 G InputArgumentName = "input",. b" C3 L0 O: u3 \/ ~0 S) c
InputTypeNamePattern = "{MutationName}Input",& w5 ^! H: C/ b9 u
PayloadTypeNamePattern = "{MutationName}Payload",9 M! l. W" Y D6 K
PayloadErrorTypeNamePattern = "{MutationName}Error",8 s- v) _. m7 j! W. V
PayloadErrorsFieldName = "errors"+ w6 j) j" X/ C
}). k: ~' ^. N2 b+ _: F7 ^
.AddType<PostType>();
* H5 ]- R8 N. a H$ V ^</code></pre>: U/ V* q1 m' }5 }$ V
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>; m4 f) i3 o5 z: t8 ?( a+ T: V
<h2 id="验证">验证</h2>
8 Q; \; j/ u( x( S- N8 D<p>启动<code>Api</code>项目,调用接口:</p>
% }% A$ j. q: F7 n, \% K<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>1 v" V2 w% y. E1 Q% j+ H0 K' }3 V
<p>终端的日志输出如下:</p>
, z5 P9 @/ Y$ ? e( |. B<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']8 F8 P7 \+ O1 J. J5 U& |/ R1 E
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title"), Y" `8 S, X( t' H
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);* a B7 _5 g3 ^. _& I
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
9 ]3 k7 N8 u" [+ X1 H</code></pre>3 R9 B3 u# ?0 n* h8 G
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>% t) U D d, H7 E
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>' d+ X2 M3 d; z
<h2 id="总结">总结</h2>9 K( K8 Y- _% `5 U( Z; t z* f% b
<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>
3 d: N" b% z1 o<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
( y$ I& K/ C6 u+ m
( h$ {, ]+ Y5 \# _- v$ j! r6 ` |
|