|
|
# C$ a# Q2 Q7 P
<h2 id="系列导航">系列导航</h2>
/ ~8 [1 h3 @2 P# o* V: p2 I<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
4 ~/ i* v; @. I" ?2 `+ m5 F( [<h2 id="需求">需求</h2>8 @, n9 g9 I, C6 }5 H) G$ r; k
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>: x& T: q" Z. V# y& ?5 S! K& |
<h2 id="思路">思路</h2>" H3 l ?0 l: l
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>+ u" F& P2 h/ W/ ~
<h2 id="实现">实现</h2>8 z5 @4 M+ i" s5 e" V9 {3 @
<p>为了保持简单,我们先定义以下两个类型:</p>
' b$ `8 S" G) F& d& e<pre><code class="language-c#">// 定义新增Post的参数 Z& i3 j" C7 I
public record AddPostInput(string Title, string Author);
# V. z7 Q8 Z9 r5 W! d
* p! Q' d( W% g+ R// 定义新增Post的返回对象
5 y1 G/ w/ z5 k; H2 vpublic record AddPostPayload(Post Post);
( Y; [4 E$ f$ P- G</code></pre>
2 X' r. O, R7 ` \- y7 d<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>/ u8 j2 ]% Q! q$ _6 S0 j; b/ \ ^4 {
<ul>
9 |+ w: x7 \% W! `' x<li><code>Mutation.cs</code></li>
% V' L# @- W2 e' k0 k</ul>
% \* ]1 m5 ?& |/ A. y<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
4 Q4 \- y, t4 H/ V$ p5 C4 h S- C8 S
public class Mutation! B% i4 z. }* r3 j
{
" `" t( y; T- X- P6 F8 u public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository); C' a( a* o8 o$ B8 i7 b8 B c
{. W! a* l) h G# e/ x7 M7 K4 g7 M0 T
return new AddPostPayload(await repository.AddAsync(new Post
# n2 q7 V7 l: s {* S) R7 B* Q! D4 f
Title = input.Title,/ _- A/ @9 L+ ]. x
Author = input.Author
: E q2 b$ n) U) V; {/ f3 \ }));
2 n; i1 a) G2 M: M( B6 l3 a. } }7 J7 f4 W* \( p, K7 ^! s
}
+ M1 Q0 @& i- X3 x3 m. O- {% [ M, O R- r
</code></pre>& w5 Z" u5 ~/ K. N5 p
<p>最后在注入服务的地方进行配置:</p>
* _3 Z; C; |/ u3 z<ul>1 b: B* c8 R, p$ @
<li><code>ProgramExtensions.cs</code></li>
0 p6 T" `9 d7 d7 {0 i- A</ul>
b3 w( Q' M# C' o9 q9 j7 ^* i<pre><code class="language-c#">builder.Services
- k' V: [ U2 r! i( O. ^3 [ .AddGraphQLServer()- a6 L- I' V9 v2 |/ P3 _0 o4 _4 d) S
.SetPagingOptions(new PagingOptions' C( T9 ?2 q1 G' u, e7 Q/ v2 B
{
1 ]4 G9 k8 p2 ]- r0 H MaxPageSize = 50,: `0 f* k% ]8 H0 n5 @
IncludeTotalCount = true
4 @* ]2 } D1 Y. V3 I6 w" Z+ m0 _ })# q; G$ u8 d/ @7 h) W3 @
.AddFiltering()
) r/ w5 b+ s5 P# n& P6 d .AddProjections()- A. i/ h, j+ H2 Q0 z: y
.AddSorting()6 X5 I) x# K |
.AddQueryType<Query>()
- t3 A" Y2 z* |) U( T# t: f+ T .AddMutationType<Mutation>()
' W2 V+ g& k. V: A9 q2 Y. G .AddMutationConventions(new MutationConventionOptions$ V! H0 z' T/ [4 d. u" o1 f/ O5 q
{
4 q: d9 _6 z8 D: [7 A) Q9 i- F7 e# K ApplyToAllMutations = true,
, h- E ?$ M1 t9 e$ l# }; o InputArgumentName = "input", ?: D9 k. V9 X4 |2 ?/ P H4 V
InputTypeNamePattern = "{MutationName}Input",
4 Q3 p. u- {8 z( h8 X# G0 Z$ l, v- w PayloadTypeNamePattern = "{MutationName}Payload",$ z& r: G. H2 G/ u# F' C, J! A
PayloadErrorTypeNamePattern = "{MutationName}Error",
* o I* Q1 v. [5 c4 k PayloadErrorsFieldName = "errors"7 E; u/ T8 {1 X: U+ H& Z
})" @) w. V6 X* O: N* c
.AddType<PostType>();8 M, X7 N7 z; @3 a2 M
</code></pre>7 Y% \% Z" U+ q# r# v
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>) N! q3 z5 d; n7 r7 [
<h2 id="验证">验证</h2># a3 e1 U4 p- R% a1 [
<p>启动<code>Api</code>项目,调用接口:</p>
7 _6 b t; f1 m0 ~5 Q4 p1 s3 D<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>! I; f( \6 d% p/ L
<p>终端的日志输出如下:</p>; {: |. D* p2 x% g4 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']+ v9 Y' F5 [6 X# b2 u
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")% |& M5 {: B* _2 }0 G% d, \$ u
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);! c) I! @& \$ V& S$ N
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'6 S4 p! C' l* N5 M; a
</code></pre>3 I1 F/ K: B9 P3 f
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>( O9 n* a! e& K% `6 ]. y
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
. m" i, |1 b- _7 T7 a" q, }<h2 id="总结">总结</h2>, o @6 ] J( r; i. A
<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>
% ^% a X! `, T) r9 ]2 W<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>, R9 s. i1 a0 z3 Q
3 R/ }" |+ I! a, o& ]$ C |
|