|
|
3 Y) L' H5 E# A, [$ b/ d<h2 id="系列导航">系列导航</h2>
' @2 Z- a4 k, E<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>. x% v* z5 ?* a0 q% g
<h2 id="需求">需求</h2>
1 N. F. e) E( |- J& O9 X2 n/ j6 ^% @2 t y<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
0 Z: s7 \' e3 g! _; ^2 a<h2 id="思路">思路</h2>
7 K: A; l2 `7 ]% o$ L: a) @<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>7 o$ f: [6 m( u
<h2 id="实现">实现</h2>" V b% B; x4 h- W
<p>为了保持简单,我们先定义以下两个类型:</p>& D7 U9 s: ~ e# M; N& J6 _
<pre><code class="language-c#">// 定义新增Post的参数! u: d* y( [ Q1 v4 f) r! Q. V2 i
public record AddPostInput(string Title, string Author);
N% c B% p) g2 W6 x4 b& e8 D2 F( }& g" {
// 定义新增Post的返回对象
: _/ Z' S4 {' `1 Ypublic record AddPostPayload(Post Post);
8 ~. c/ {5 t: j0 V5 r</code></pre>; R7 v* e6 s6 R/ g [+ B
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>/ v' j9 T5 A7 r+ S) F
<ul>
- d' n! H3 [3 s' ?<li><code>Mutation.cs</code></li>
' j! S) _. h3 y</ul>- G# T; ~9 x [, f4 G) ^1 ]
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
% X$ @/ [( V2 m7 x" d2 h
! |0 v+ `; I5 ]% p# Zpublic class Mutation1 M7 G+ E& v1 ]0 {
{' _) y8 B1 t% h7 B, T! U
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
. N! Q* ?# R1 s/ o5 k# X+ d {, v% }( a- X7 @+ f6 d q1 o2 w
return new AddPostPayload(await repository.AddAsync(new Post. V2 {$ b) d' k4 h$ z( v
{6 k( B4 |" b" a# m* D$ ^6 F: @
Title = input.Title," E U+ V- v5 H+ o$ s, R# P# d$ R
Author = input.Author
, ]) M9 w9 f& F }));0 U( J) X$ j" R% i" [; L
}
) B7 i. p. i7 K}/ b& w, L) T e" i% t V( ?
# v1 A$ o& n& \/ z4 S
</code></pre>6 t+ t/ v# b8 ]* N8 d- {7 N
<p>最后在注入服务的地方进行配置:</p>' P/ I V( A- E+ }
<ul>
2 Z, ?* y+ p* F6 N2 {<li><code>ProgramExtensions.cs</code></li>5 n9 c1 I+ ?; S& Q+ J7 Z7 G3 S1 e
</ul>
) ~- l8 B& r* k" I$ ]: N3 ~7 k<pre><code class="language-c#">builder.Services
' H0 O& \1 G# c& C& F3 A1 A% G .AddGraphQLServer()( b* C2 Z8 K3 L8 N- O
.SetPagingOptions(new PagingOptions% E2 R5 t5 P* Y% }
{
8 r7 N2 R6 G0 M6 V0 z* w8 f- i/ k( C MaxPageSize = 50,& r# ^% c6 x) _4 V
IncludeTotalCount = true! E" F( u) y, {2 l# E$ x
})" O1 F% I1 E0 P! d; S6 \
.AddFiltering()
4 J$ g* L2 N; ~' |; V5 R- y5 \$ z .AddProjections() r+ f0 D4 R! E
.AddSorting()
% r, C% S9 j. I .AddQueryType<Query>(). s+ Q9 _8 L+ x9 n2 x2 q
.AddMutationType<Mutation>()6 a5 `6 i" n' C6 t
.AddMutationConventions(new MutationConventionOptions
" y9 P( m0 G" G) a f {
& z$ q) b) U ~. w1 X5 B% G1 x( E ApplyToAllMutations = true,
3 c# e/ E- g0 Q& c/ ]. t InputArgumentName = "input",9 B |' Z% d" t1 b( y* b5 Y3 o) F
InputTypeNamePattern = "{MutationName}Input",
& W- N1 ?; L0 t; P' `: A& I PayloadTypeNamePattern = "{MutationName}Payload",
/ F9 j: l6 x6 ^$ K; a, f; {/ V% Q PayloadErrorTypeNamePattern = "{MutationName}Error",5 J( n3 O, e/ H5 _5 `
PayloadErrorsFieldName = "errors"' Z" c5 }; n# W
})
+ X' p! w6 _, Y, z8 V4 o$ E, r* R3 Y .AddType<PostType>();' o5 k, S5 {0 c) I& j
</code></pre>
" W) Q$ m0 \; e7 n<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>9 A$ W) ~& p4 E/ N1 b- J
<h2 id="验证">验证</h2>
2 {* T0 A% G/ c& u: u2 [<p>启动<code>Api</code>项目,调用接口:</p>
7 Q* }, T9 n- ?% H s, t1 D1 B<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>9 w9 h" }3 H6 C; C' _+ K. s0 ~
<p>终端的日志输出如下:</p>: z; D" R9 K2 L& _5 h$ w1 Z, K
<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# }9 \# R, ]1 u( {7 AINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")2 ^5 c7 W# Z5 T! @8 }
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
; `# D/ K5 f2 B( [[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'- E! u3 V2 ^% E% A. k
</code></pre>
$ c$ x) J. q( {7 K8 }. D7 h<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
5 z" ?, k8 x" ?5 M' i0 e<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>7 d8 _" k6 B/ @
<h2 id="总结">总结</h2>
" F* V0 Q1 Y8 @5 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>! O P$ q# F/ C& D9 J
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
, t( ]4 V1 E# e# }) f: E) l( f
. a3 l: W) \5 W( Y" R' d* @ |
|