|
6 R/ K8 J! m% P. i<h2 id="系列导航">系列导航</h2>, }2 P8 o9 t5 g& b# a, O) i
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
# `3 M$ |1 o4 v9 t! x<h2 id="需求">需求</h2>7 z0 J# J! [+ w7 V; l, |- ?( G5 F
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
3 D! h0 ?. A* `3 |8 Z! u0 X u2 L<h2 id="思路">思路</h2>
) B: k" b) P2 B. W3 ?" j<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>$ e. b* p# ]% P# m, B; g
<h2 id="实现">实现</h2>, k, M8 C( T( a8 r) I4 t
<p>为了保持简单,我们先定义以下两个类型:</p>$ O8 D/ }8 N2 y; p: f
<pre><code class="language-c#">// 定义新增Post的参数$ n4 |. G0 i9 m2 ]2 k5 f- p
public record AddPostInput(string Title, string Author);
$ U5 ]6 |- X1 ~
4 @% i% J: \5 B// 定义新增Post的返回对象& X/ i2 L; B! V$ ]0 G, L
public record AddPostPayload(Post Post);
1 u; g- V9 X3 [4 r</code></pre>3 A* c4 b% l. k9 A9 [+ [! O
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>3 w$ b0 d& H, z& D, l$ P( b' g
<ul>; Z, s; i- s/ P! v$ `8 j
<li><code>Mutation.cs</code></li>& R+ I& J8 N* ]/ I3 P0 l& \; }
</ul>+ }# Q$ G" A) j% J( e+ _' k: B
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
: G; R: J( T U+ e: S, M7 c: u- u% Y/ T9 T5 C* P! n
public class Mutation
8 b! |. i# B+ P" H{5 |# F& Q( C% `" i
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
2 f0 e/ T Q0 i3 y! ^1 _/ T {2 `5 l0 ?" b% i/ Q7 j
return new AddPostPayload(await repository.AddAsync(new Post
' m7 P2 X9 p/ J* p6 c$ R {: U( B" m' t V/ `6 C2 ]. v W- r
Title = input.Title,
8 M9 E5 Q) N) {- o; f Author = input.Author0 n9 L4 c6 \1 R$ _- d0 [" c! z
}));
& p7 E( d8 K5 Y, m6 u, Z2 t }
Q: v6 B$ N5 g3 C1 R}8 }8 O+ m4 j* S# _. H" p
* S4 e; K7 y; t( t8 G/ z
</code></pre>
; }5 m& D4 R5 R( q- ^& P5 `9 o* ^. B<p>最后在注入服务的地方进行配置:</p>. |$ i8 \+ g6 `; b- O
<ul>1 o, g3 S/ B" ~" s+ s
<li><code>ProgramExtensions.cs</code></li>
- M9 ~* o( P+ {$ n& C- e</ul>
( f* X, q+ X" H I4 |<pre><code class="language-c#">builder.Services
/ ^) B* n6 |0 ]8 _" }( M .AddGraphQLServer()
6 a7 W. Z, x& W2 s! o .SetPagingOptions(new PagingOptions* c7 s" G; P, S2 M+ ?
{
6 I5 E! b V- E! ~( I( x6 K MaxPageSize = 50,( u: _) g+ W7 V
IncludeTotalCount = true; V% ?, L& p# c' B1 G
})
9 {/ {, ^ H2 Y' }3 A .AddFiltering()
7 L# I: e7 S- D; ^3 ?, w .AddProjections()
+ L4 a" M& c& ^. L5 A1 [0 } .AddSorting()- q! h0 T0 Z6 E3 w
.AddQueryType<Query>()
8 ~4 u3 `- F- O+ w& C .AddMutationType<Mutation>()' o7 A- @6 V6 p; x
.AddMutationConventions(new MutationConventionOptions* O3 Q- ~( n( D
{8 ^- O3 d0 J/ N, v& u7 J8 Q5 d
ApplyToAllMutations = true,/ A8 W: A: v @6 {# i
InputArgumentName = "input",$ ]. p9 v! S4 A* q$ s) x
InputTypeNamePattern = "{MutationName}Input",
# ]+ h' u; Z) ^9 @4 {, x PayloadTypeNamePattern = "{MutationName}Payload",( z3 o$ b b" ^5 Y' r! R+ I( X# G# v* E
PayloadErrorTypeNamePattern = "{MutationName}Error",9 a( x4 u3 Y- V
PayloadErrorsFieldName = "errors"
. ~$ C5 r) N" T' ?2 C0 A }), l9 J2 {3 Y2 g7 E* ]
.AddType<PostType>();/ s: M. z1 \+ L# M' [! k" _- O
</code></pre>: k: |1 c6 @) n. j5 m- O
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
4 v$ O, Z% R9 k$ V<h2 id="验证">验证</h2>
+ B7 T1 c/ T) K% U5 z {<p>启动<code>Api</code>项目,调用接口:</p>) d" ?; g4 d, G& i
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
8 g1 d, [" X" I! Z, e1 B<p>终端的日志输出如下:</p>1 }; b: D! Y0 r5 c
<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']
* ?# ` `1 |+ }8 e8 Y1 J# W" tINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
2 m# k# S/ ^& l8 [) EVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);3 I1 g* B, ?; b* V `) S
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
, h" \3 A2 A/ q/ X% i& e$ f& ?% N</code></pre>
- w# u8 b( V/ p# u) c<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
5 c' R# @, m4 g: H% a<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>9 H2 n1 q& z6 a, q! F0 n! Z
<h2 id="总结">总结</h2>
, o) O/ Y) a% ]% K( _, j<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>8 o4 b# D' n Z% I- ~9 ^+ ]1 T3 ~
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>1 \, k: `+ w9 }/ O. p) v- r
" z- k" k$ }1 q7 A! k+ [/ [% x" S |
|