|
|
! Z3 J2 ]) T! z" A
<h2 id="系列导航">系列导航</h2>
# _$ Y- D0 r9 z4 J& c/ b4 F Y2 X<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>; x+ |% d$ i: B' r g/ W
<h2 id="需求">需求</h2>, z; l) ^+ K6 f2 r+ O
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
3 V) n- j: U- v" W3 ?8 f, u! f, a<h2 id="思路">思路</h2>
) P3 m: J1 j3 ]% m- s<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>. j7 [% k. E/ @- D, K
<h2 id="实现">实现</h2>8 z7 a5 B7 r- O- |( ?" }+ T
<p>为了保持简单,我们先定义以下两个类型:</p>
) P5 q$ q8 S/ m# C& D<pre><code class="language-c#">// 定义新增Post的参数
. u) f. j/ O3 Y! B2 M8 Qpublic record AddPostInput(string Title, string Author);% V; A# c6 ], E
( Y f( c1 _+ u" k$ q
// 定义新增Post的返回对象
3 T8 ]: X" p/ N0 j- j1 ?3 dpublic record AddPostPayload(Post Post);7 M& y9 u. R) h) r
</code></pre>
6 I& H0 [3 a' U<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>& n; q3 \- ~- b4 V
<ul>3 j2 R2 l9 w1 }+ O7 l( d
<li><code>Mutation.cs</code></li>. l( v/ W* A( `7 F# t' }/ H* o
</ul>
8 c' e3 \5 V- L/ Z& b" |<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
( k( n+ {7 L* u) {; x5 M$ x
+ X' I* `# G6 Rpublic class Mutation' e ?6 ]/ _; t/ [
{
R, u# y; a4 i, K- R! b8 K public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
7 E7 O* F( I! l$ [+ ~( m8 O$ I {- e# h; V5 ~2 A# G q5 @! H
return new AddPostPayload(await repository.AddAsync(new Post, \" {- T4 `7 r1 U6 Z9 T! u
{; g' b, H6 e) a! v! G
Title = input.Title,
% m# _$ O7 P# c4 T8 e8 \: v* o n2 l8 i; U Author = input.Author
0 m0 X5 A, l3 R* W! m }));7 H. P9 {. H8 y
}
( h `1 \- Q" }& v# G9 |}
0 l9 A8 j( a+ x3 w* M$ n$ a1 x* B( \' A2 E# X
</code></pre>% l6 I v7 o: u. ?) A
<p>最后在注入服务的地方进行配置:</p>, n, N' p$ r9 a. z
<ul>
+ B8 j- M( M9 D<li><code>ProgramExtensions.cs</code></li>
7 n+ C' b* D& {; ~</ul>8 n, Y+ a- Q3 C* |! q2 Q8 D7 Y
<pre><code class="language-c#">builder.Services
; t/ `, t: F' A/ x, J) t* Z& P .AddGraphQLServer()
* N4 |0 h6 z" l7 p1 c# I .SetPagingOptions(new PagingOptions
( {, j! e5 ?+ k0 S2 i* s8 d% ^6 `3 v" o {& x8 U/ x; \& ^9 n% F& T
MaxPageSize = 50,8 d2 `7 ~ l0 I" M
IncludeTotalCount = true
3 G' t4 A) m% W; s3 p* G. b4 W; G: r })
0 r# V O7 I5 v3 A' B: Q .AddFiltering()
) [' X+ n4 q5 Z$ D- y) Q8 s .AddProjections()
/ d4 @% S/ r1 l" g L' G .AddSorting()- }8 w' F: z" Q5 T7 X; u- [
.AddQueryType<Query>()0 N% x8 C1 G& V+ y( {% g8 I" j
.AddMutationType<Mutation>()
: f: S0 v# b0 N2 N* X) c .AddMutationConventions(new MutationConventionOptions
* w5 `( \. e% a' [6 s {
, X+ X: c Y' ?5 B ApplyToAllMutations = true,& a! m5 a5 x$ h) e
InputArgumentName = "input",
0 U0 K7 X) O6 j) _, B- x5 Z5 N; [# g, M InputTypeNamePattern = "{MutationName}Input",+ @ {8 `5 W$ |/ _! P6 M. h2 G2 U. I
PayloadTypeNamePattern = "{MutationName}Payload",$ e3 y8 s! m7 [
PayloadErrorTypeNamePattern = "{MutationName}Error",- z n1 x. [. E! G& j7 g |: C
PayloadErrorsFieldName = "errors"
: ~$ X, ~) l4 w7 B# y })
2 {( O+ l$ p8 @; C8 X/ {; n .AddType<PostType>();
) J* W% B1 S: J- h& ^) r, q</code></pre>
7 P h! L- C0 `) M<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
8 R! B* h$ x2 z# I3 Q7 M" a F2 i<h2 id="验证">验证</h2>2 H9 e, J: p) R8 v; \1 e
<p>启动<code>Api</code>项目,调用接口:</p>. d, r. p- ?) y ]% V
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p> c/ z) E! `1 M: D
<p>终端的日志输出如下:</p>$ [$ P }1 ]5 G D' V2 A7 j
<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']; l9 i8 h5 B! K3 N( X% \
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
5 t1 }' n7 S6 ^9 O' Y8 q dVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);' p; ?# w- v+ z' a# U
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'; x* V U2 O3 _! i2 h
</code></pre>, ^ r! n0 x$ n
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
* V0 ]7 E* T& e. u. W8 a! j2 Q<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
( R& q5 W! T, {9 P6 c- ^<h2 id="总结">总结</h2>
, o- e4 V5 t# U# r& V. K<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" C* Z2 f+ Z2 p+ l0 K2 O4 r- g<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>2 {$ b; w4 O0 G* A- ^
0 q$ b; s! }# K
|
|