|
|
& b3 w; Z* _0 G! a0 T, H
<h2 id="系列导航">系列导航</h2>% `' W" u I' c: i' U' f! i$ T
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
6 @' q( t+ C' ~5 [& V0 z- D<h2 id="需求">需求</h2>+ s+ Z8 H! a! c/ G: s
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
' G. Z" k/ a& }3 k' n1 ~<h2 id="思路">思路</h2>5 ^* ^0 \, X4 n
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
5 d' W8 H1 n+ ^# E+ k- T<h2 id="实现">实现</h2>
6 B! @3 l' }; ~" ~) _<p>为了保持简单,我们先定义以下两个类型:</p>
4 p o* c; ^% a! h<pre><code class="language-c#">// 定义新增Post的参数
3 p8 u6 V9 s; k+ _0 N/ @+ ppublic record AddPostInput(string Title, string Author);
- ]: V% o4 c0 R& `
, r/ a% m* u9 ?; m* J& e% W// 定义新增Post的返回对象5 o0 a, a7 z- V/ o2 K
public record AddPostPayload(Post Post);, a: Z4 `0 L. t) g7 G1 v
</code></pre># [7 }0 s- P5 F* V; p" g
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>3 {; o( M$ \) e
<ul>
0 A9 l! h U0 \1 q" b<li><code>Mutation.cs</code></li>7 C# M" W5 s( K* |8 W
</ul>
8 j& M2 x5 v- a/ y<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;6 _% r' V% C6 C; `" z- U W) p/ f- e$ L
( f7 i" q9 G( B, k' s2 t7 S$ @
public class Mutation
8 K3 g7 l. `- s0 o4 w! [{
" W) _ L- s) ?9 C8 `6 L0 e) [ public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)! D2 ~4 a! k% S) H6 P% t
{
* c! h( A& {) _+ N return new AddPostPayload(await repository.AddAsync(new Post
/ N: Q2 m5 _# a) q$ W( z {
1 Q) D9 i% i9 ~# o& f M% g7 N Title = input.Title,
4 ?/ G" k: C# O" t# n8 N& j/ u0 a Author = input.Author5 o, [( @' l2 u+ E
}));
& A- ^. U! E# a% _; ]+ T" i }! f6 y+ T3 L/ E2 e9 A3 d
}, C6 U7 ]% `* a, p: b v' D$ k. H7 T
5 N) H" q' s& C6 A: w v/ k</code></pre>
! d9 K3 }. Z+ o- ]6 M9 I# T<p>最后在注入服务的地方进行配置:</p>
1 n# i6 y: _! C, t/ H( U<ul>
0 T! W) }' ]: \- E+ m1 `<li><code>ProgramExtensions.cs</code></li>$ R8 G D' g" c. {' H: U6 s
</ul>: c* }1 X' w1 q
<pre><code class="language-c#">builder.Services# v& B: |# u9 D- @* Y
.AddGraphQLServer()4 P0 ]) O0 o# A
.SetPagingOptions(new PagingOptions' C2 r* S E1 ]
{! A+ F& c5 p2 E; j# r
MaxPageSize = 50,
# S j) W9 d" ^5 }* ^( M/ _) M IncludeTotalCount = true# }0 \. b4 o& J( p8 _
})
1 H1 x, ]/ l+ C) v% |% H' H4 G .AddFiltering(). e' _3 x/ M1 Z" O5 t
.AddProjections()4 h; w7 N. S! j# _' |( O9 R
.AddSorting()
- @6 B0 Y$ |! t" r2 p7 X- X .AddQueryType<Query>()* F( ]3 W% Z# c6 ^8 G9 [2 Q& R% F
.AddMutationType<Mutation>(): }% J& T$ f9 O) l2 U$ e2 z
.AddMutationConventions(new MutationConventionOptions8 u) f! J9 v1 [9 |; ~2 G3 |, V' i7 l
{
# b: n+ v7 N2 e9 T. {" ` ApplyToAllMutations = true,* E N, v/ ~1 f
InputArgumentName = "input",
/ x: J5 X0 g* M# w* a, |* t3 J InputTypeNamePattern = "{MutationName}Input",' ]" h. f% ?% K" i" K1 ~
PayloadTypeNamePattern = "{MutationName}Payload",
% a B1 I* m" S& e PayloadErrorTypeNamePattern = "{MutationName}Error",) q+ [2 V' b7 y: B; t& P' a
PayloadErrorsFieldName = "errors"+ n7 W0 K I5 s! f
}); u* V! w4 H9 |* f
.AddType<PostType>();/ @2 `8 H& s& r9 C0 h9 |
</code></pre>
" I3 n5 H4 n- m<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
4 ?$ h1 e, A. X<h2 id="验证">验证</h2>1 ^5 l- {% @9 @% ?7 j
<p>启动<code>Api</code>项目,调用接口:</p>$ q( F! m3 z( v, O# T/ d
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
! j, e1 p/ D; \<p>终端的日志输出如下:</p>
6 X# V( I7 T8 k, \- [<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']
- z3 v6 m( K) H9 k# ?INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
, J6 n6 z( e2 j; [3 q. Y8 }VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
( t. g6 ~" N# G! Q( J+ }[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'% Y" r2 n* i0 I* p) |/ ?2 ~
</code></pre>
3 S4 e0 L8 o1 E. ^<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
' ~8 G2 K* O2 {6 }6 D<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>4 p7 y, \ V4 C+ h- F6 _
<h2 id="总结">总结</h2>( P- U- f5 W0 Z- A5 l& A
<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>* `9 N* {, P( F8 N! s: o' a
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
7 W9 N2 q6 x4 w0 B; @. ^5 Q! z' w4 h
& c6 `/ k( r- |2 i" N7 c |
|