|
|
, C2 n/ [- B+ X3 z1 J
<h2 id="系列导航">系列导航</h2>) K- c$ o- m6 O5 s5 Z/ }
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>$ p% a- I6 t2 U: \
<h2 id="需求">需求</h2>
% i, E: c) u3 ~8 @, n0 @# C* u<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>' R7 x( t7 m c5 L
<h2 id="思路">思路</h2>: w. P0 f2 I6 [4 R3 l9 H. r ]
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>5 @# H3 H9 ~+ y# L7 t. A, J
<h2 id="实现">实现</h2>
7 ?) D$ [+ t) `/ G' u<p>为了保持简单,我们先定义以下两个类型:</p>6 ?. N* a: O6 e' I3 ~. o! ?5 v1 n9 y
<pre><code class="language-c#">// 定义新增Post的参数
4 J& Z: e6 f5 [6 Upublic record AddPostInput(string Title, string Author);5 W& h1 S6 ?. z: D
; F }! p2 D! O6 Z; r8 J6 g/ W
// 定义新增Post的返回对象& ~' N1 D% a7 o( E5 c' ?
public record AddPostPayload(Post Post);
0 H, s. v9 R$ w* D1 a& A</code></pre>( o- {" p5 ~ D. x5 H0 D- X! R/ b% p: K
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
$ I, ?. {+ M8 ~' s( n& v<ul>& C$ T' }! R: @: v
<li><code>Mutation.cs</code></li>) ] `9 h- ~9 w5 k7 X$ s; o
</ul>! E# _& ~5 Y5 I2 ?% o
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;$ E: i- n' I" d7 R5 ~! ]
- F" `; j+ _- Opublic class Mutation# c0 k9 z+ }# Y9 \5 o1 ~6 Z7 `0 P
{ C& ?, z( Z9 I0 | W9 b
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)2 b; ~, N$ D% o+ ]/ d+ o) |
{1 q2 U* K3 c. k7 Q0 y: x
return new AddPostPayload(await repository.AddAsync(new Post. b; ]7 S" |, m7 h( y8 T2 V9 j2 U
{
0 K. U" ]# e g7 y& y Title = input.Title,
( J" D0 n! P2 e; j s! x) B2 W Author = input.Author* t) m" }) _& v- a* r
}));6 C5 U! N( c7 F0 R0 ~4 w
}
. J+ n! P! {' j$ E8 r: O/ q8 ^; [}$ f$ j* O' P7 B. d" v9 O' f
- j4 p: |/ l" }* {' k( I0 s. A* }& J3 B& s</code></pre>
, @0 L0 z8 O8 E/ b- p7 a6 y: U: `<p>最后在注入服务的地方进行配置:</p>
' ]# [- O: O) ~- f<ul>2 L% D8 ]+ }' p" H
<li><code>ProgramExtensions.cs</code></li> j5 G, Q+ K/ F6 f# S
</ul>
# N9 f3 P! X. b" n" k1 I3 M! n<pre><code class="language-c#">builder.Services0 M4 k+ ?- b5 I
.AddGraphQLServer(). E6 [1 s8 M" q& r
.SetPagingOptions(new PagingOptions
7 V0 I% A ~& v3 K% l {2 |7 l/ R/ T. q# ~ {& j; i" h0 X: Y( ]" d7 L
MaxPageSize = 50,
& E' d# W6 l9 r/ P0 y IncludeTotalCount = true' L! E9 N! O; a
})* O& c4 `& z/ H) I! d
.AddFiltering()6 P) V+ b" L9 X% Y2 p [: Z& t4 c
.AddProjections()
7 X3 f+ N7 D: h' H; c .AddSorting()
4 T% o# p* }+ t1 |; F .AddQueryType<Query>()
) I; h+ W2 }* q7 B$ a; |# Y; i* E .AddMutationType<Mutation>()
% s- w; X4 t% a, y .AddMutationConventions(new MutationConventionOptions
# @/ f: D, C+ v {0 {' Q) f/ q* B$ H: u
ApplyToAllMutations = true,) |0 W* d# Y* O6 B" `
InputArgumentName = "input",$ b" P/ }: } D8 f4 K
InputTypeNamePattern = "{MutationName}Input",( m. m W# Y" g7 ~
PayloadTypeNamePattern = "{MutationName}Payload",$ z. [- q. v1 u8 ~3 U
PayloadErrorTypeNamePattern = "{MutationName}Error",
' ^: B3 z$ z. i! c- A PayloadErrorsFieldName = "errors"
9 x; R( C: C" |7 n$ y+ Q })( ~) Q5 k# n) Q
.AddType<PostType>();3 E3 \& P: t, g6 o
</code></pre>% h. }8 f( ^# M% Y4 ~
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>$ g8 B' b+ q. |7 q* C. W1 P
<h2 id="验证">验证</h2>* `9 @4 `. T6 F, R' ?
<p>启动<code>Api</code>项目,调用接口:</p>
( D2 U p$ Y' E7 x d V' r<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>! Z+ h, q8 X `( Q' t# V2 N% {
<p>终端的日志输出如下:</p>9 j* H- K& e' 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']
; `' }/ x% C! E( V6 T0 gINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title"): ^9 t w" L0 Z( k; ?4 n
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);" N* H: ^6 L. K3 ~- l
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline', {% b$ Y: i o7 D
</code></pre>
" r A9 o+ s$ v2 H# }# n<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
5 H5 N% X D/ p' O9 C. F<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>" J `: n* ~7 X- `
<h2 id="总结">总结</h2>" M |% m& |& r5 w" T4 e4 s
<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>- U( C; n9 M( M1 j
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
5 J$ Z. L3 i, G$ _" f
3 a' k: e! b2 v# j& u |
|