|
|
) Q5 ?2 {0 G8 m) l& [
<h2 id="系列导航">系列导航</h2>) Y' x) i* a" [
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>5 E4 `$ \$ c+ e6 o2 \! s# Q: H
<h2 id="需求">需求</h2>7 k4 w* Y2 H; c1 {9 v* b
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
0 |; N9 o' S% Z<h2 id="思路">思路</h2>
, R1 ~9 q1 w& B! c<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
7 F) y7 {; M( \) J<h2 id="实现">实现</h2>! K9 R4 G1 w6 s
<p>为了保持简单,我们先定义以下两个类型:</p>
( Y7 i4 N, {; x! `# w U# @<pre><code class="language-c#">// 定义新增Post的参数
; p$ `/ q: p/ r) p4 _2 |5 z! spublic record AddPostInput(string Title, string Author);
6 I% Z, y; y5 z& c
, c% k' O. O T2 V: F# {// 定义新增Post的返回对象$ ?' Z7 X) h- r8 R3 d8 Y5 l
public record AddPostPayload(Post Post);
4 I' p5 Y" @1 O1 O: _3 e</code></pre>
! v& E/ M: G$ v1 S<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
0 M4 c1 ]8 p# L( O* i! Z4 b$ O9 z<ul>
' o8 \+ L5 g( L5 W" p# }& o<li><code>Mutation.cs</code></li>+ x- b! G, F- j; G
</ul>( w- i5 U7 o5 O6 h$ U! ]) D9 T
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;: I* N% }. w4 B0 G' X# K- r6 F
! _* A# J3 T5 ~
public class Mutation. y/ n# O$ e5 A; v
{4 }2 e s( N$ }8 d" o
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)- y. t2 w8 o( ~' Z) b7 [" f/ }0 Z
{
8 S' D5 f! ~* Q return new AddPostPayload(await repository.AddAsync(new Post4 ~6 }- L, y5 G, \; U9 O6 y. h( y
{- \; z" @% W- Z& E
Title = input.Title,
7 m6 n& C3 Q2 t. e Author = input.Author
) d# ]; h& A. i Z }));( W i% K# ?- i* w
}
, C% F% M/ M- n4 i; b0 ?}7 Z* H2 g0 d. v3 c
/ D$ r* Q* a: f& |8 Z! K- b1 {) c</code></pre>! E9 j0 b/ p) [& d+ g9 \
<p>最后在注入服务的地方进行配置:</p>8 D" f, A* Y7 t! o2 ]
<ul>; Z& A+ _; R# e8 ~
<li><code>ProgramExtensions.cs</code></li>/ c c8 h' I7 G6 A2 P/ o! h
</ul>
1 b; g$ u2 M0 c<pre><code class="language-c#">builder.Services3 h# @3 i, G: u# P' b
.AddGraphQLServer()3 ~$ L$ [! W4 @" Y- o7 L$ z
.SetPagingOptions(new PagingOptions0 g* S& U5 O- C4 w: i: A
{, u- N" s* V" P6 V" p; R
MaxPageSize = 50,
( b& K5 F# P2 y0 G# T) X' p IncludeTotalCount = true. L9 s' g# b4 q' O7 B# k
})& v9 A& q- a$ s* S7 X% H
.AddFiltering()* d# K6 \: O( M* f" i
.AddProjections()3 u& F9 h r) `% ^3 {9 J1 X/ |
.AddSorting()
V; y5 z; C0 \. @ w1 d' \4 h, [* E* Y .AddQueryType<Query>()! [# y A. `4 t& ^; Q
.AddMutationType<Mutation>()
9 c; h# n- F( Y1 @ X) g2 ?+ s .AddMutationConventions(new MutationConventionOptions
# e# u/ Q. c1 y ?( Z {
- F, s) e6 ~% V ApplyToAllMutations = true,$ L% @, z* a1 E2 n/ R+ Z# W1 @
InputArgumentName = "input",9 Q" `9 X6 c* r8 r9 \& D
InputTypeNamePattern = "{MutationName}Input",. S- b0 I- D2 }, a: L
PayloadTypeNamePattern = "{MutationName}Payload",
$ _9 Y9 x% V# s5 X4 s/ f PayloadErrorTypeNamePattern = "{MutationName}Error",
4 I5 [' q U; T( H PayloadErrorsFieldName = "errors"
: U2 I& m2 [5 V* L. G& B' ^) X: R }); D. M4 x3 G/ U0 }! E; K5 \2 v" D
.AddType<PostType>();- r4 f8 A7 h" [# A
</code></pre>
2 ~) p8 \( X' W v/ O<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
! j) @8 J- k D5 G. @0 q) d<h2 id="验证">验证</h2>
/ Q4 P% d9 n7 C9 j' s ?2 C<p>启动<code>Api</code>项目,调用接口:</p>
# U Z9 ~, b, S$ E# K<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
6 {+ v$ Q. t- p- Y# s3 S<p>终端的日志输出如下:</p>
. {+ E/ m3 a5 R$ Y* W) b+ Y! T, m<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']
4 ^5 n i* X3 q, s: i% aINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")5 E: Y) w3 q( i# u- `: `
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);4 L/ y6 i* x! p/ E6 `: T" T; B
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'+ Z+ k/ p% R! u: K, Y+ i8 f ~: U
</code></pre>! R: @4 K$ @3 f& _; S* W- x
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
% M3 ~. e6 @0 [/ [- m- ?4 |) v: O/ H<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>" A( }& p4 G. d$ O9 f' ^2 n; ^
<h2 id="总结">总结</h2>
1 X# a) C; k! P<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>( c/ x9 m g5 ^9 F) h: X: g7 H
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
$ ~/ Y5 \+ k0 x' q7 f1 o0 V
7 s: b- M: m; p \6 G9 q |
|