|
|
8 q( L8 A0 g* L. u/ F8 Z<h2 id="系列导航">系列导航</h2>
. \# p$ j# |6 w' k. \- l<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>8 {0 Q6 \- o7 O
<h2 id="需求">需求</h2>
5 i2 P3 B7 j! [/ x<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>. L& _) N% b0 l# x/ T6 \* J- L
<h2 id="思路">思路</h2># C3 E6 V' |$ g
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>* m& i1 P# e3 c/ ~
<h2 id="实现">实现</h2>
3 G2 w1 Y8 g0 k( C2 C<p>为了保持简单,我们先定义以下两个类型:</p>
& G8 V$ e+ d _6 V) a<pre><code class="language-c#">// 定义新增Post的参数# R" d1 i. Q: }% N1 w/ q; U
public record AddPostInput(string Title, string Author);0 t2 S' F5 J6 k4 p& P
1 b! i- m5 p& |7 u# I' R// 定义新增Post的返回对象/ N. \- O0 \4 R- l# k1 h
public record AddPostPayload(Post Post);
l1 C! }' [" o. W) \</code></pre>
. [" l& ? M1 B<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>7 g( n2 j1 e! K. a' h
<ul>6 R h0 j2 Z+ U9 }
<li><code>Mutation.cs</code></li>5 n4 _1 B7 M8 ~! V2 {0 `
</ul>
2 Z0 S9 y8 k, }# M<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
/ r" I2 A# g/ f0 u
8 E, F! @: _5 @ B, E2 gpublic class Mutation
: J" A7 ^. _$ H2 I1 N' u{
# Y; V0 ~5 b8 c( B+ d public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
* X, L" Y; a. \ {1 |2 P* e' W) |0 t- r# ]/ g6 \
return new AddPostPayload(await repository.AddAsync(new Post
' ^. A6 n- i$ L3 c( i {0 z( F: J3 p; s% b6 p- O
Title = input.Title,
: D1 i& _% X; b6 a* K Author = input.Author+ I; q3 Z" {$ |. [+ e
}));3 B2 z/ Z* \7 {/ i1 T
}
0 S1 ?( P- E) y# N6 @2 n# e}! O5 n" }$ [+ H
) U9 p: x9 f& }0 D8 m7 p9 N
</code></pre>+ e% j0 q/ j# ~" g% B$ Z
<p>最后在注入服务的地方进行配置:</p>1 h2 t& c6 p6 j3 l5 L1 Q
<ul># {. {! Y4 z7 @7 ~- F& F
<li><code>ProgramExtensions.cs</code></li>2 Q) s' F0 c1 r9 x4 @/ {
</ul>, O4 @6 A3 k" w3 ]. U3 h
<pre><code class="language-c#">builder.Services
( X) f, l) I5 K8 ~& v .AddGraphQLServer()
7 c% {( u% {) c9 o- J .SetPagingOptions(new PagingOptions
/ C: I* L J& l/ U" e0 n) \# ]% Y {
9 N* `7 o' M( h' K MaxPageSize = 50,
. s+ V' B% z/ R( L4 m% C IncludeTotalCount = true
8 b% T( {! U6 ^# N4 \ })
& L& F2 A' r: Z$ W/ s" U7 C .AddFiltering()
7 }7 z1 l2 e" ^5 `% L; q .AddProjections()
3 r. X: n! h0 R4 U, S" n6 X% z .AddSorting()7 K# M, L1 G' q. _7 n( o3 |
.AddQueryType<Query>()+ [3 R5 m/ Y8 Z, Z" X
.AddMutationType<Mutation>()
3 w* A) }0 f6 c: C: u8 G .AddMutationConventions(new MutationConventionOptions H- Y& m" }- q+ O
{+ f3 i* {( G& M, _
ApplyToAllMutations = true,
8 T6 E" P! I" Q6 N2 T0 T, S InputArgumentName = "input"," K! E# q+ m$ Q, g# W+ s" C
InputTypeNamePattern = "{MutationName}Input",
5 ~ `$ E8 F% ~+ [6 H PayloadTypeNamePattern = "{MutationName}Payload",/ ~+ `2 Q/ c* x* x
PayloadErrorTypeNamePattern = "{MutationName}Error",! b+ X8 m+ G6 y* j; a5 h2 X7 y, ^! L
PayloadErrorsFieldName = "errors"6 e( x2 Q# N" H
})1 ^0 m4 s) u/ X) B \+ v
.AddType<PostType>();
' w5 U' J z" Q1 ~0 f4 M, v* q</code></pre>
5 _3 {( I; K# e+ L* q: ~<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
& f6 D6 [2 z; J<h2 id="验证">验证</h2>% `; G- a, U' b' T K/ I; Y1 z
<p>启动<code>Api</code>项目,调用接口:</p>; C; G$ |* }- v3 y) `* g
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
: R* |& t# E6 f" X% b" N<p>终端的日志输出如下:</p>, I: A/ E' S# B2 r3 x7 D1 e2 z( T
<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']. p0 I5 r" H6 b; Y7 M+ V; W
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title") p4 x c8 Z6 ~6 Q# K
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
# N4 W3 S; f+ v: _: R2 P! F4 x[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'- t- L) p. [' F6 _
</code></pre>; t8 L( M5 f6 M+ V: K
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
$ l3 Z+ V+ f5 N) T* X<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
8 n- y/ w+ f/ N1 M) b% P- o<h2 id="总结">总结</h2>: z/ v# W; l0 T: j: b8 }
<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>
, ^& W9 ~& r/ h% u* _: M1 o& t2 @<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
& T9 ]% \6 g6 \( r: s2 I. L( f" T% o7 T: R: w' j8 Q
|
|