|
|
' b! L5 X. j. U( D7 X) T {
<h2 id="系列导航">系列导航</h2>
) F: d6 [3 t, N9 r+ G5 A' k' P<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>( A' z) v3 ^+ Z6 f& f
<h2 id="需求">需求</h2>
; ]! t9 L, J9 q) F<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>3 s/ Y7 w2 h" ~9 ?; S
<h2 id="思路">思路</h2> a# Z/ H1 S( B7 @1 n; Z
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
3 Z1 j' X- @# J0 p# B& \<h2 id="实现">实现</h2>
( ]- w) D$ j# N5 t( H: O<p>为了保持简单,我们先定义以下两个类型:</p>) S' z0 y4 Z- z# \% U
<pre><code class="language-c#">// 定义新增Post的参数
- ?. @, ^8 W' x* E lpublic record AddPostInput(string Title, string Author);
7 a* Z% A* q9 [, T8 x4 a! v! A1 K3 S' p! [3 X9 W5 ^! s
// 定义新增Post的返回对象
/ w, N: e# h' E, z. C' Kpublic record AddPostPayload(Post Post);6 \" `% i2 b. t( w- ?
</code></pre>2 z, l: S( |. n7 p m
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>- ^# d/ }) K9 z4 g0 B# C
<ul>' z2 p7 E9 b3 c+ C/ G1 |) A& h4 Q
<li><code>Mutation.cs</code></li>
$ D0 ^5 h, X& F `1 K8 L% R</ul>
* M T! A7 s! k& I<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;/ ? Y r: ~0 B b6 w. @ N* ~
6 ~3 x# K# F7 k' \ gpublic class Mutation d$ \ r8 k! d6 F. H$ r0 m7 b' Y8 p
{8 p. N. }3 o! N- }* c
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
' z3 g. Z/ t: A, M/ p3 F {
5 [) Z- M, C6 d% v% H; n" Y return new AddPostPayload(await repository.AddAsync(new Post* g0 w0 \$ K/ i. x
{
8 \; \ }4 T1 X) U) u3 q0 m# z% @ Title = input.Title,
8 p) o5 m1 W, h5 g/ k Author = input.Author G0 s3 c/ h) R$ K- M4 y, H4 \
}));
( w4 [3 u- q" u# E1 V% O }+ z* y# \5 y: s) L3 n( |0 H! b
}
4 x# k3 O. G( Q0 Z: d$ j& ]+ N8 @! K. y+ G+ v6 s+ X U/ O
</code></pre>$ G! r8 Z% L) H" C+ Z& f
<p>最后在注入服务的地方进行配置:</p>3 R: t$ p9 H' d
<ul>! C. F. j! Y: G3 _
<li><code>ProgramExtensions.cs</code></li>, G# `& O9 Y" j T* |
</ul>
7 W' a0 G) w" B$ s/ @/ P<pre><code class="language-c#">builder.Services
' O3 }% a, _9 Q. o2 F! P .AddGraphQLServer()
+ r G% A! j* z+ t, {% ? .SetPagingOptions(new PagingOptions
. o9 \, {) M9 I( q) J) S) i {9 P- I3 s0 ?* C& b3 I( y
MaxPageSize = 50,9 C, h/ G0 m5 o! D3 I0 u. ~
IncludeTotalCount = true
! d+ ] |, h: ]; B- g _' p. [ })
$ c% ]& M- c* `# _& ^ .AddFiltering()
$ t" D u. H1 B .AddProjections()9 }0 }7 X- h* H/ C8 E& K$ b2 p
.AddSorting()
' w: T, h }9 r. i! x .AddQueryType<Query>()
2 } _9 {' N+ `8 P, s; J# w .AddMutationType<Mutation>()% _5 [" V& L- H& L' B ], q* @
.AddMutationConventions(new MutationConventionOptions/ W( \* J- w2 M |
{2 {" u3 b4 L1 ^) y. M0 H: r9 {% o
ApplyToAllMutations = true,
9 L' \% a$ q& y! u InputArgumentName = "input",+ c# I. E5 h) m+ b, [ ?' K# P. l3 n" Y
InputTypeNamePattern = "{MutationName}Input",
1 @$ n5 U) Y. v- Y( _- g0 W PayloadTypeNamePattern = "{MutationName}Payload",) U2 W( W$ c; R
PayloadErrorTypeNamePattern = "{MutationName}Error",/ P S# n6 U! L: b
PayloadErrorsFieldName = "errors"' {7 A* d$ j5 j3 M4 q
})
" `; [1 z& z7 j# g2 g- G7 h/ R .AddType<PostType>();
2 p/ }" @9 X* T M/ n</code></pre>: j( C$ `5 k: W* [" u
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
! y% \, e8 ~$ d" B; d<h2 id="验证">验证</h2>$ H& C% o& g2 N- K3 R, b8 \
<p>启动<code>Api</code>项目,调用接口:</p>* M) ]1 i6 \' |& @) n3 w3 c4 t
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>- M' L) z+ a; x: z5 n; n+ {
<p>终端的日志输出如下:</p>
( v3 Z3 v i& y, C+ l% F$ C* e% O<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']
( A6 M0 }2 }' {INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
' n6 C1 v( h2 z; ?: p8 E; HVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);- f( b: H# B x$ W; H) ~
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'" m% ?+ R( i9 p. n' L6 l
</code></pre>3 Z3 L% x, m3 Y; n
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>4 v M) f& M$ T* I
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>" H4 D" r5 W; t5 p5 Q0 _/ E# E8 m d
<h2 id="总结">总结</h2>
' i3 n( n. W* f2 D<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>! s) m0 O2 H, E6 G- O$ b# g+ |
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
, s$ q- J9 M o1 H3 }( g7 p: ?. e
6 j2 u5 ?5 C2 ~% Q) M# N8 ?$ s. Z& o( g |
|