|
|
0 {9 J8 v# a( ]: @
<h2 id="系列导航">系列导航</h2>
5 e- I/ Q" R9 w2 _2 r<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>- d! h- k# C* d& n/ o6 u0 G
<h2 id="需求">需求</h2>- @7 b( s: @8 |' p F1 r
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
3 X7 F7 D3 j8 L5 E4 \0 `8 {<h2 id="思路">思路</h2>! q* K4 Z! ?/ a( @! l
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>* @6 ~2 X2 l* h9 I |; V
<h2 id="实现">实现</h2>
' ]( K T$ W) d% g$ A" q<p>为了保持简单,我们先定义以下两个类型:</p>8 x2 o; P; @+ O
<pre><code class="language-c#">// 定义新增Post的参数
9 x( x ^! `; l9 ~; L1 r( G! Spublic record AddPostInput(string Title, string Author);) j' ?( q: k& ^; N1 P4 e
, E p! _2 P6 e, k+ J
// 定义新增Post的返回对象* E% t7 t* ~' P. H3 z9 a
public record AddPostPayload(Post Post);
5 ^7 N' H+ N) C$ [' X, s0 H- \</code></pre>1 d- \" e5 W) {! n
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
5 [8 K( ]5 x9 B& t" E<ul>
! O' a# b% Q! P<li><code>Mutation.cs</code></li>
2 J* o3 w1 a4 H: u: w</ul>
, k) @: Z& a& v<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
' p8 n4 G& S& O1 `
8 N8 y# M& e; @5 |public class Mutation/ }$ H6 B0 d- m/ O2 m+ ? z) R% \
{7 b: C; b& D1 ^2 z! u, m
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
! X& T1 A7 U% S F4 w* E0 n {
- Y. C% @* `8 t- W return new AddPostPayload(await repository.AddAsync(new Post
6 G+ n: A: Z+ @6 q: `0 g" t {
8 y o5 L/ e) \2 f3 v7 P7 R Title = input.Title,
7 x5 m8 }$ P" h Author = input.Author# R+ @# n. O1 w, @
}));/ S: u4 c! w8 z1 d: J0 \- y" K
}
) A) D5 c6 d6 _* N$ m}
' }: \1 M& d7 }8 s- f/ K. f0 g
. S$ p* R" w- o</code></pre>2 Z! ]1 b1 I A/ ~# G
<p>最后在注入服务的地方进行配置:</p>
4 h2 T1 I4 p3 V% T5 T T5 H0 e& V% x<ul>4 V7 J. c D( g. _2 V
<li><code>ProgramExtensions.cs</code></li>
1 w. R5 G1 ^8 P0 O: O* P' L3 N) A4 b</ul>
) w2 z2 g7 M$ Z, M9 D# Q/ [( P<pre><code class="language-c#">builder.Services" E2 n2 c9 C3 q# z2 q3 m
.AddGraphQLServer()' d" \1 {2 n: S# t/ ^: q9 F
.SetPagingOptions(new PagingOptions
9 h6 u4 ?( s0 w& W" w+ g2 J {, Y% J) M' y9 ]5 f, p: p: o! [
MaxPageSize = 50,' a P( c1 F% C1 M& }* u. v) d
IncludeTotalCount = true
- C; ^4 s4 u9 p3 A. U })
; _9 `0 v7 F6 W" e' Q' z7 I .AddFiltering()
$ \& T2 X$ J, G n, Y6 i0 I" t .AddProjections()# Q+ l9 U# i) P. b) V4 n
.AddSorting()
' c# M* I7 b9 O( g .AddQueryType<Query>()5 v7 Q R& M+ _- e5 e ^6 K1 ?
.AddMutationType<Mutation>() O* o: s* l* L# m2 d( h8 ?
.AddMutationConventions(new MutationConventionOptions" z- X" F; ]6 i, ^- \/ W6 ~/ k
{# Q' I% Y, H R7 c
ApplyToAllMutations = true,
( I( R3 }. P/ [( r3 G InputArgumentName = "input",
! ?5 |% ~3 X6 F8 |3 V InputTypeNamePattern = "{MutationName}Input", g" R5 t2 z" T, E
PayloadTypeNamePattern = "{MutationName}Payload",) v: T4 d% c% y
PayloadErrorTypeNamePattern = "{MutationName}Error", j; ^0 y5 u8 d- b( H
PayloadErrorsFieldName = "errors"' n. ]. ~8 u; e" G' o
})' _& H. T/ j7 E
.AddType<PostType>();6 @$ B4 q# K; q: N! b T
</code></pre>
5 y9 E' W- X; `& e2 p5 d<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>+ |. h- i# d- @, h( n& n
<h2 id="验证">验证</h2>
3 H+ P' Q$ u4 h4 O" ?' G2 Q- m<p>启动<code>Api</code>项目,调用接口:</p>- k* [+ e4 [! Y6 d+ A& A
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
( z l1 G8 I3 s I3 k6 r<p>终端的日志输出如下:</p>
. w6 [2 J! b( G6 E1 i) 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']/ t# d N0 c6 K% j" q
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")( g: R0 [7 U1 @6 p4 g( g+ i
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);: S' u& T# Q; ~6 }' z8 _, b$ a
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
n( q# \! H" C& V& u. p9 m3 C</code></pre>; I) u0 z# l7 W! I! P
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
# x# c5 W' M* I5 K<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
( P) l- O8 W8 f7 m1 J<h2 id="总结">总结</h2>
: V7 _& {$ h: i1 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>& ^, m! F0 e& Y- l/ a' \* f
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
. ]* g9 I% e1 W, O# g. R- l! @
; |7 N0 W) P4 j/ l' D% @2 u5 F |
|