|
& o. r. @$ W4 W9 D6 z$ t
<h2 id="系列导航">系列导航</h2>2 v1 x2 \2 P7 ]: D* ?. L6 q4 b) Z
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
0 I$ ^# Q3 ?* b+ h% v, d<h2 id="需求">需求</h2>
! @; q! |7 C. F% d8 c<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>9 V5 R' j% B( @* C! S8 `+ a9 u c
<h2 id="思路">思路</h2>3 ^: }: x {% K/ L4 D3 `7 q
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>% Z3 E/ w, y7 J) S6 @/ ?( @8 {
<h2 id="实现">实现</h2>0 P; _1 y8 a2 H8 W8 S' R; I) @3 ~
<p>为了保持简单,我们先定义以下两个类型:</p>4 i z4 I& {+ i9 J9 Q
<pre><code class="language-c#">// 定义新增Post的参数. x! F# ^' {' x, l& V5 D& F
public record AddPostInput(string Title, string Author);1 R& P4 S& f0 q# ^) i) ^/ ]
% ]2 F) j! P' f- B9 R// 定义新增Post的返回对象
" B; X# x" W3 C& vpublic record AddPostPayload(Post Post);: B9 o) k8 r+ t& E- a8 y0 [/ `
</code></pre>$ h# ?% c6 H9 `$ b0 X( R$ w! V
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
, x, l: A& {6 z8 u% G<ul>& u w' Q, m% V0 x' H X- y' d
<li><code>Mutation.cs</code></li>
7 c. ^ T0 F; v- S2 o* P</ul>$ Y+ `: E; c: j# _, b2 X
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
' Y/ }+ L2 _. `4 J* {* d% i3 w+ r. v% f8 [# W. X
public class Mutation
# a* j9 Q4 Y. ]0 W [{2 B) W# N2 u( v8 D
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)' F$ K! s5 B1 X5 @; p# d
{0 Y7 V) d9 m* b- d' U9 g3 s, G
return new AddPostPayload(await repository.AddAsync(new Post
* _7 J0 S# v8 @* U" y6 Q8 B* R {5 ]. l9 K9 f# m# s- ^# o" Y
Title = input.Title,
, c$ J: J- @1 W) F# Y% ] Author = input.Author
6 P) x& ~4 ?0 ~( ~6 s }));
) u: J% Z0 s } }9 {3 l& p5 X( ~3 P4 q9 E3 X% U2 i& l
}
# k" {2 b, v# T, g
# i$ ?3 `2 Y5 C) A* |</code></pre># a. ?+ R4 F3 N; \! i2 F _
<p>最后在注入服务的地方进行配置:</p>
) [8 K9 B+ i: m+ V<ul>
$ \+ x/ F' |! q<li><code>ProgramExtensions.cs</code></li>& G; ?2 Q9 y2 N& d1 Q% z+ D4 M
</ul>- I+ W: Y" E2 ?; r7 Y( W& r# c
<pre><code class="language-c#">builder.Services1 H- {; S2 l5 R; G {
.AddGraphQLServer() r& z2 R& B) L6 z) x! G
.SetPagingOptions(new PagingOptions
# G( j4 ~( d3 y {
2 s& Z6 R3 w, q3 ]1 I9 L: a MaxPageSize = 50,
; v, q# y' \: X" E; c IncludeTotalCount = true, h1 ?7 k( O3 j
})6 i: @9 s6 y( [3 S) j; K
.AddFiltering()+ F7 P- i) y6 R
.AddProjections()
6 ^% \0 [: }* U F3 s. h- l .AddSorting()
" K( Z0 }9 C9 r: w* h .AddQueryType<Query>()/ j8 |- [# X; P% ~! i- f
.AddMutationType<Mutation>()
: n$ y3 ]. h' u* `0 B4 @1 R .AddMutationConventions(new MutationConventionOptions
; J! Z' m* A4 U {
, T/ M, F7 S) p ApplyToAllMutations = true,
" \3 ^; D) l& ~4 ^( Q InputArgumentName = "input",
3 ?$ _% O8 v4 E; p8 k InputTypeNamePattern = "{MutationName}Input",
- I, U' Y1 M. C7 c1 a7 _ PayloadTypeNamePattern = "{MutationName}Payload",
& L( w4 N3 |7 X/ O) R PayloadErrorTypeNamePattern = "{MutationName}Error",) ~9 o' V1 E j7 I' j9 d
PayloadErrorsFieldName = "errors"& n0 g* H1 g# P0 p q
})
: d! ?" d* k; @ .AddType<PostType>();
/ \: S/ i$ t! f" w% d0 x</code></pre>4 I0 \- y9 h* [7 T) q
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
8 h: o3 L" Y0 X9 w% G/ ~<h2 id="验证">验证</h2>3 ?9 k- Q9 ]1 Y
<p>启动<code>Api</code>项目,调用接口:</p>0 ^% r3 w4 s8 I! Z/ E k) c
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>9 Q: y) @4 d0 T7 E' b
<p>终端的日志输出如下:</p>
) d+ w( Z/ P" H+ x: \<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']
, ]" r! r1 J; {( R9 }INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
/ P9 W5 r( n5 k4 m. [VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
3 g3 y. t* ^) C4 L* I Q[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
5 f/ X' M) ~ h1 x! h% H</code></pre>
# U/ F1 B* Q, H3 o4 g, r d# v<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
7 M3 H; I$ {0 }) w<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>* W1 e' W; |- K' W2 q) ?# }5 X
<h2 id="总结">总结</h2>. q- D7 _3 u* Q' f# x, \4 q
<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> t: y! v, o* }0 `
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
: d! R! |/ b: m; {' R. y- P
! [' @( O: h; d* l# n |
|