|
|
* i8 |4 n+ N9 _6 {, H$ J: f: M<h2 id="系列导航">系列导航</h2>
/ W6 Z9 m B! K5 _<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>+ U/ C8 w$ ^' I8 }% U- p( y2 k
<h2 id="需求">需求</h2>
: j' F O0 E; r4 f# d<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>& {% n: P: n4 X& i
<h2 id="思路">思路</h2>! y1 o! ^$ O9 g& R% d8 E9 A, o
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>9 J( w8 L! A1 Y3 u) d7 u
<h2 id="实现">实现</h2>
# F9 S1 {/ k' M* t8 s! ]<p>为了保持简单,我们先定义以下两个类型:</p>0 ~( \2 J" O! G" ~* L
<pre><code class="language-c#">// 定义新增Post的参数
5 Q, y, B( I0 d7 Tpublic record AddPostInput(string Title, string Author);( j8 S! f. n; L; N! f0 t2 z
& O' C! A/ V; O5 _ f, v
// 定义新增Post的返回对象
2 S: g7 R/ [7 t0 X4 W' X3 H# Gpublic record AddPostPayload(Post Post); ?" a4 h- {) u( ~; X7 z: B
</code></pre>3 k W: P* n6 @# Y" J% o. i
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p> O) X- v2 _; e" }6 @$ F2 Q
<ul>
7 A' n$ R5 k7 {0 ^<li><code>Mutation.cs</code></li>
& h% d7 p" |0 L# I, M0 I+ {</ul>
. o. d% F; _8 a0 W: v w<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;" X9 K+ L" r/ c# ?. B8 \" G
8 M; U; v; a7 m" e* lpublic class Mutation2 [" S! k! J. a/ \* s
{
% w: N1 p. o, V5 Q8 ], A public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
% K8 e. Y) g, b2 l1 P5 `! R9 q {- ?# f# i. ]0 K
return new AddPostPayload(await repository.AddAsync(new Post) m& k' h, H' G1 ]) B
{
7 ~ I. w: C+ W+ N7 W0 B# l Title = input.Title,, I5 n @/ S: Y9 d7 q. d
Author = input.Author
; x8 N5 N$ K: `3 X, y1 Q1 ~+ d }));
* D0 U/ A! K7 {/ e8 V }
. m& d" J5 H" C, r% ]5 P}
/ @) H0 ?$ \( p8 y
$ I- ?0 g, {2 [8 t% O4 U</code></pre>
; @; Q' u! H! a6 y) i<p>最后在注入服务的地方进行配置:</p>0 x- q# x3 y* b4 O/ T( v) U
<ul>( C! l# y8 z: I. B" I9 J
<li><code>ProgramExtensions.cs</code></li>
. k3 w+ w* T1 X</ul>
% J, L `" S4 _<pre><code class="language-c#">builder.Services
# ?6 q4 O& ^% F6 [1 j .AddGraphQLServer()7 g* K- Z- Z. N
.SetPagingOptions(new PagingOptions
c9 `3 D$ T+ J- z; j c8 C; d {! B. Q0 @) t* a( `1 U' x7 J, e
MaxPageSize = 50,! J' n$ l/ x# I4 ~5 H& I8 [/ @
IncludeTotalCount = true
$ u7 n5 [' a! O1 l }) `/ j" S0 Q6 d6 U) D+ ~' P
.AddFiltering()
4 g& X; F8 `. { .AddProjections()
4 T# M2 Y, y' v [* y+ I4 w8 u* t .AddSorting()" M8 F7 s6 @7 ], n& O
.AddQueryType<Query>()5 H6 D$ [$ a! B4 v& r) J5 o( H
.AddMutationType<Mutation>()& o/ E# O; a# _/ _
.AddMutationConventions(new MutationConventionOptions. ?; ~* {0 J( J0 d( c5 Y" r: [
{
& g" ]# ~" O9 P6 V ApplyToAllMutations = true,* Y" Z- a+ c" j* F. I! @2 G+ l
InputArgumentName = "input",- y d) U/ E$ S" C c; `7 @' n
InputTypeNamePattern = "{MutationName}Input",6 _+ A- }. \6 @
PayloadTypeNamePattern = "{MutationName}Payload",7 M* B2 m1 k* d' v* A
PayloadErrorTypeNamePattern = "{MutationName}Error",
2 E; X+ i6 U: j+ c m, O) V PayloadErrorsFieldName = "errors"
w, |% [+ C7 L$ r4 @/ s })
1 B$ i* A- A0 I% H& K& A" z .AddType<PostType>();
/ m! Z2 v- R/ `! T/ ] C6 ?6 I( o</code></pre>
, R5 |$ Z& n/ l# b! ^* d. O<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
v: z5 w K' l) K5 j) i<h2 id="验证">验证</h2>
/ s& `0 W* X1 A9 h9 u<p>启动<code>Api</code>项目,调用接口:</p>4 I2 k% H0 [8 @1 } p
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>) o' |* B2 g4 ~$ C9 o% g" |
<p>终端的日志输出如下:</p>7 q3 O; B( X# I
<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']- }, o; |' u9 O5 O. _9 X- g7 z; l
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
+ ]+ Y& U3 |+ O m S& tVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);& S3 i9 u0 y0 K6 \; W9 z* r' Q
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
( v- A+ B! v w& q- N' l</code></pre>* p& O/ }3 f9 B9 c' r/ O
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
8 e) t+ ~- P. z<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>1 o8 p; c* p' o3 \ b
<h2 id="总结">总结</h2>
$ x! l$ a9 R6 e7 |% I! k' l2 T<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>
" P) L4 a% c: c Y J1 j<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
( k Q7 `' e" v4 h4 x& r2 ^* s5 d( K% t, y
|
|