|
|
! `1 q% o* l( o+ S7 b8 Q<h2 id="系列导航">系列导航</h2>) U6 w$ T6 b# W2 o' \
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>2 O* r+ r+ M& A# K) o
<h2 id="需求">需求</h2>
( y$ d7 I8 c4 j2 ^( N. n<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
4 A- a0 m0 h" e* _6 L" L# f1 y<h2 id="思路">思路</h2>6 o6 m8 Y4 Q4 Q
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>" |7 U, ^8 ?! u! x7 i- U6 I A
<h2 id="实现">实现</h2>- |' M6 F( q( [; ?5 b' {
<p>为了保持简单,我们先定义以下两个类型:</p>
' B( Z6 J" }4 D2 u- b! P<pre><code class="language-c#">// 定义新增Post的参数
7 h9 V- I1 Q b5 C6 A: s, Xpublic record AddPostInput(string Title, string Author);" p5 {4 h: |3 m8 P( o8 D
9 J4 ]" r0 T( ]- W4 S8 B: g' F// 定义新增Post的返回对象
1 B' s9 {" T% p! I& Epublic record AddPostPayload(Post Post);8 ?3 h m0 ~7 O7 { x. d& e
</code></pre>* f. C% }% }7 L
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
' I7 M0 n' ^; B5 b! i" J. z- b<ul>( j$ @0 ?, n4 v1 C2 }! ], _
<li><code>Mutation.cs</code></li>4 ]8 P. u+ L* x" V' n9 V* q1 H; ~/ X
</ul>6 ~/ r& w" h! I
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;$ d: X+ g, x: G, _) ~7 `
; [- P* \, {1 O/ U0 Bpublic class Mutation
4 S' F" R0 C X* E! j{% m% N T6 I7 d0 H
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository); T2 J( u6 S( e
{
6 O# }8 O. f @; ^% @+ q8 [ return new AddPostPayload(await repository.AddAsync(new Post- |9 n5 K7 N+ K3 E3 V
{
* E+ T! q% G, v3 |& z Title = input.Title,. ?- G) v. ?+ b' U; X
Author = input.Author
3 r4 k( v0 w7 C' i }));! W' Y8 s( v2 x. L- M
}8 p, X; P' ~8 r* n8 j
}! h3 P0 Z5 g# A U9 x
6 p9 I1 @( @8 |: M) q- j; ]$ g
</code></pre>
9 A( v, Q' v% y3 R% c1 m6 z# C, p<p>最后在注入服务的地方进行配置:</p>8 E6 P5 {) o0 y$ {& @/ o
<ul>
2 X) }+ d* a& h2 d; i, P3 j<li><code>ProgramExtensions.cs</code></li>
. @, h5 |( U* Q3 w) h</ul>8 ~/ Z4 r/ }: f
<pre><code class="language-c#">builder.Services& _$ W# t# T/ Q5 J
.AddGraphQLServer()
: ?7 g3 |$ j# C9 D .SetPagingOptions(new PagingOptions
1 W4 p% w7 j4 ?# I8 _, X3 i1 r" ]/ h {6 N& R8 V* ^! A, z- j. B
MaxPageSize = 50,
8 f8 W- K# [7 G( V IncludeTotalCount = true
. d1 u, ]- {( P })- q. r U' Q- k
.AddFiltering()
: Q4 c. E e9 c! e8 R% k .AddProjections()
: x- m( H9 E2 ]( o- W .AddSorting()
4 u. g, k+ f' Y, Y4 O O .AddQueryType<Query>() Z: U+ z7 V2 s3 h9 m" K! C6 W: S
.AddMutationType<Mutation>(), W- H5 ~ S" m4 a% ]+ @& f' Y2 r
.AddMutationConventions(new MutationConventionOptions
4 l: _+ A( Y9 h4 u- S, w: J7 { [* Z {) [& u) o6 I1 x
ApplyToAllMutations = true,
, Y. n$ H5 N. b9 ? InputArgumentName = "input",
- F8 ^; K5 |& ` g! w1 K1 A* h InputTypeNamePattern = "{MutationName}Input",
* N2 Z1 U( ^# [1 P PayloadTypeNamePattern = "{MutationName}Payload",
- f5 Z5 G5 B p) i- E PayloadErrorTypeNamePattern = "{MutationName}Error",
+ B- Q( D8 x$ c( ^0 M" P PayloadErrorsFieldName = "errors"
- p/ N8 C7 x5 E })
+ [% V1 M8 c5 u$ Q* L. y .AddType<PostType>();, ], O+ R {% }; e5 u% {7 q, f. G+ \3 P
</code></pre>9 x: `+ v1 ~, J3 i" a0 X r
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>6 B/ T) ]9 K; s/ q9 `" H5 G. g
<h2 id="验证">验证</h2>/ e* z( d/ ?6 ]; p! ]+ z
<p>启动<code>Api</code>项目,调用接口:</p>7 x- {% C6 G. a% t
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>$ B$ U) B( u; L0 T0 A
<p>终端的日志输出如下:</p>6 m C% d5 x8 G4 A, N; W
<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'] p. t+ [$ E% ^6 X$ I
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
2 w; }5 L( b0 F+ GVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
2 J5 p0 c! I/ |6 W[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'" z) Y+ L0 m5 g( V( S3 `
</code></pre>
! Q, ~+ n7 `* M3 l) m<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>( {4 w. f4 |1 G, C8 B8 \3 ]
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>8 S& V5 H# v* b6 ~9 Z; b f4 Q
<h2 id="总结">总结</h2> V5 v$ B& \# I
<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>! ^& l7 x; A) y1 N: q" }/ _! Q' \
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>6 d/ j4 ^7 W v" l
; y2 {) s; c$ ] |
|