|
|
) H7 H$ k: V, |: b; ]7 c1 F9 U9 }- p
<h2 id="系列导航">系列导航</h2>+ u: h9 _0 T4 ]- r6 U# n; g
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
7 J0 @3 Q5 \3 x. q6 P5 j% M<h2 id="需求">需求</h2>
0 {3 J% p+ B- \, v: E<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
3 w5 a/ s2 N6 T8 i<h2 id="思路">思路</h2>
q% C% N# x# j o, R<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>( ]! Z- U+ n2 O4 w7 |6 A
<h2 id="实现">实现</h2>
( l) s; i$ |$ p1 f1 ]1 X6 E; n<p>为了保持简单,我们先定义以下两个类型:</p>! v8 n( y. N) q; a4 w- Y: H" |2 d& B3 B
<pre><code class="language-c#">// 定义新增Post的参数7 Z% Q( w7 ?' Z, e O4 p4 D
public record AddPostInput(string Title, string Author);
, ] V) @ m2 J( ~) A# x9 n: l4 |: S' J1 v1 K3 A* g) U
// 定义新增Post的返回对象
' I5 O7 t5 Y2 ?4 K. [public record AddPostPayload(Post Post);+ c, l& d5 v- O, | C9 ?" p9 F
</code></pre>! L6 Q' J/ |7 \% W; n' r
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
5 U8 A! f" \6 I. m<ul>( W4 M0 d* ]* Z
<li><code>Mutation.cs</code></li>7 T0 ~) d ^0 e
</ul>. P+ `. H; U$ ?3 E
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
n" z6 n$ \8 e3 m# S+ ~. p6 c4 x
public class Mutation& B0 n" {4 m ]5 Y7 a: }, w
{- u; W5 Z X( b+ j: R. `" |
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)& ^0 O& X+ |* y( ~# b
{6 Y6 d+ S% G. U! M* ]) v8 d
return new AddPostPayload(await repository.AddAsync(new Post
+ x& Q0 Y& \8 h3 V. a+ X {' ?5 t* J2 g" f1 {/ y& N0 h9 k
Title = input.Title,* {( Y7 A" R- P* `& O+ t/ }
Author = input.Author- z4 {2 }$ p6 D5 @' m5 X
}));
3 ]1 q8 N6 r8 O8 s }
- a @3 S+ M: p a; l+ u1 T" x$ |}' I5 @- Z/ v, B* G
1 e. {: y8 U. |# ^7 g- c6 J
</code></pre>: x: z. b2 x" G( ^2 a; x
<p>最后在注入服务的地方进行配置:</p>; J4 o: E7 U2 @$ l% @/ |) }
<ul>
9 T s0 h$ M! o' h: N: C+ |, h<li><code>ProgramExtensions.cs</code></li>2 c" l$ v4 H# }+ f7 n
</ul>
( k6 S: b) Y4 l1 h" Z8 L3 t* ^/ X- I! S<pre><code class="language-c#">builder.Services
3 i0 N9 j! i9 D& p .AddGraphQLServer()
6 q7 v" t/ m5 [ X! K! H .SetPagingOptions(new PagingOptions
! I- u( }' i9 d; [# z/ {+ k0 z {5 [* K& A- C1 Z
MaxPageSize = 50,$ m8 @% ^$ t: m/ i7 a( R
IncludeTotalCount = true+ y* V7 `5 D3 s' X& s0 M
})
( q+ I! @7 h" k .AddFiltering(); }0 ?" j0 B/ t( c
.AddProjections()% g; f, n! _1 @% P4 I6 p9 B& D
.AddSorting()- ]- K, S2 ^: ~4 _9 q$ X
.AddQueryType<Query>()
# p5 p+ W; x2 P* q# W .AddMutationType<Mutation>()
8 h% o3 u/ X# Y! i' X4 {% c7 F2 H& \$ @ .AddMutationConventions(new MutationConventionOptions- T- c* t# x6 L8 E/ N
{
: Y- L$ y9 u( V4 ]+ z# N- w ApplyToAllMutations = true,; K4 M; v/ |# i! Y+ W2 R0 @* Z. E
InputArgumentName = "input",' G q/ b6 D+ O, B3 q5 A5 v
InputTypeNamePattern = "{MutationName}Input",
! V0 y/ V. S6 A+ { c+ S' f PayloadTypeNamePattern = "{MutationName}Payload",
+ G6 e" ~9 D" o! M; F$ i PayloadErrorTypeNamePattern = "{MutationName}Error",
! ^! A- ?. B; } PayloadErrorsFieldName = "errors"
" W- `% y {5 n# d3 Y' q, g }): N y$ `' {5 l$ z& O5 Y F
.AddType<PostType>();8 p, r, `- p; @0 Z, y( J
</code></pre>2 U& I& r. D! U
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>* k4 b" o5 C7 U1 r" U0 E! y
<h2 id="验证">验证</h2>
1 e7 H& F: }9 [6 L<p>启动<code>Api</code>项目,调用接口:</p>
$ J' J) o V" c& I1 }" e6 w: X6 h<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
5 A2 f. M3 k3 N. E<p>终端的日志输出如下:</p>0 Y& L- Q" {4 |9 R% G. `( P1 V& ]
<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']
b) m% n5 ^" R' }, p. `INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
" ^, X; I4 p* U6 _) dVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
0 P6 A6 j( i3 `1 B[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline': I5 z. [! Y5 v+ f7 Z
</code></pre>9 Y1 W8 E8 _' F& L
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>8 m7 d# d$ H% B( U1 d2 ^
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>. v' }' ]) y4 s/ c S: f" e# F* @
<h2 id="总结">总结</h2>* f+ y4 ~ M( p1 l2 x W
<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 I- x" R% r5 R& t/ w3 O: @" c
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
9 s2 i8 w1 s$ }# {. E. }+ D/ B4 \9 S1 W' Z! ], c" C
|
|