|
|
5 v9 K, M" c* Q1 x$ {3 B<h2 id="系列导航">系列导航</h2>1 i/ s$ X' U u9 K
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>8 L1 Z3 j w. v- Y" C( D, f
<h2 id="需求">需求</h2>' N- ~$ S4 w5 H6 l
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>: b& `$ f; E! O/ N/ A( N
<h2 id="思路">思路</h2>
6 u0 u8 u& b# D7 P$ y: |<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
- Q, P. u) T, ]- b8 C8 T. O0 p( g3 h<h2 id="实现">实现</h2>
* I6 R) n5 a# z( T<p>为了保持简单,我们先定义以下两个类型:</p>/ l# \7 v- C Y# y& L
<pre><code class="language-c#">// 定义新增Post的参数
- E3 Y/ q6 c# G# upublic record AddPostInput(string Title, string Author);
8 V0 s; Z+ m) m+ O1 g' G% A0 J$ O
// 定义新增Post的返回对象
- c8 X) d+ P9 \1 Mpublic record AddPostPayload(Post Post);2 z7 r/ o/ {+ ^/ M" P1 [
</code></pre>6 f8 X. C4 v' |
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
5 q$ g, X$ s l2 x9 a$ C. Y. ?$ I<ul>
$ o' ^/ K- C+ o1 s5 j# j* f3 F<li><code>Mutation.cs</code></li>
9 ^& S5 B; D, `</ul>
! b* r! ~8 ]" _( a7 Q. q" h<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
+ q, W9 f6 G" Q5 [" X, H: |" M3 u
5 C V/ P$ g6 lpublic class Mutation, ~ C) D- q6 P/ |+ t' e) m E
{
6 w+ Q4 m) X0 o7 }/ \9 r9 ^* ^ public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)( v# s/ M& S* b5 Y( u
{! P! O# P% m+ [& L/ f
return new AddPostPayload(await repository.AddAsync(new Post: e3 P( ^7 E7 \6 \5 \
{
; @, ]* r2 h' J, K1 i Title = input.Title,
- T& ~& C( d+ N* p$ W: u Author = input.Author
. q7 `& Z% N8 h$ V7 p. v0 V! N: ` }));
" {+ Q* C+ E& Z: R V2 @! ~ }
1 ~5 Y6 G( L8 L* ~9 w; D. Y9 \}* |( p4 I( S. l1 D5 c& g l% q7 a w
) o& @! G# y" U& w1 @9 P</code></pre>; w# T7 V% ~8 {* a0 [+ u
<p>最后在注入服务的地方进行配置:</p>
7 L# i3 Q. k+ D* U2 O* B<ul>; F) Y+ T) j; l! u' e" o1 I; Q$ z
<li><code>ProgramExtensions.cs</code></li>
- A9 t7 n6 J* _( O& W+ E</ul>
: E1 R0 O8 Q6 P- y8 s7 @<pre><code class="language-c#">builder.Services
8 m5 m+ ]; q4 S1 H8 W .AddGraphQLServer()* t( M2 X% _+ D5 l
.SetPagingOptions(new PagingOptions" Z1 \) o7 @1 F5 s
{/ g5 u3 z! Y1 G" y) S; d
MaxPageSize = 50,. J5 J! s% _9 a" P& {$ ?' b' H5 u
IncludeTotalCount = true; A+ F. o. u: C+ K5 S1 y
})
2 B8 P+ C2 z* Z* O+ O7 W ^ .AddFiltering()8 b; {+ T1 h+ t' M) f
.AddProjections()$ u3 b& \9 `6 r S
.AddSorting()2 d. ^; ~/ A6 p! v
.AddQueryType<Query>()- m) J/ M& E' b0 m+ P, O4 O0 i
.AddMutationType<Mutation>()
C7 ~2 T2 [5 w5 L$ ^ .AddMutationConventions(new MutationConventionOptions+ T8 \, f0 h/ O/ q( h7 V
{
# \% x6 r& b8 c7 i7 u2 c6 ~1 O ApplyToAllMutations = true,1 }% Y% l+ U2 h. z( _2 M
InputArgumentName = "input",
4 x8 h3 m8 V/ r' t InputTypeNamePattern = "{MutationName}Input",
2 U" {: m9 G- q PayloadTypeNamePattern = "{MutationName}Payload",* z7 a3 S9 M8 Y. U
PayloadErrorTypeNamePattern = "{MutationName}Error",0 ?. h+ B/ ]+ Y$ I4 @
PayloadErrorsFieldName = "errors"
0 {7 K9 S1 K {! z; k( `# d })
* p ~5 d( B0 U .AddType<PostType>();
" U. r5 _- D: G2 Z4 N</code></pre>
" p* e5 [" E) `% A r x" p& E! p<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>' }' `" @8 h6 }& i6 O3 _
<h2 id="验证">验证</h2> n/ E6 s- s7 |, V
<p>启动<code>Api</code>项目,调用接口:</p>
6 L( x/ }) A9 L$ `+ J<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>! ^7 P- p q+ L, D& m0 J
<p>终端的日志输出如下:</p>* L; W& [4 H. b$ W3 Q) u, [2 r5 Y
<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']
. H6 T; u) w2 V+ Y, A6 iINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
5 a2 u5 R6 s( v) v' \- Q! k6 d7 ]VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
6 a3 U# w, B3 \; y$ r[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
L/ p6 e# w1 Z5 v. _1 j3 [ z& G</code></pre>
! o9 j$ @3 I& O; O7 Q% ]4 n' c<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>! {7 L6 y( d6 V, ~, [: z
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>* @/ A( m+ ?* p4 B
<h2 id="总结">总结</h2>2 F+ H! ~; F& T" C5 `+ r3 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>& }( _+ ]4 A# u( X! c' Q7 y3 r
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>% l/ Z* H- x. J$ ^) _
; \- O) }" M1 z1 f1 H |
|