|
|
0 f4 ~7 f$ Y& _( C7 ]1 S
<h2 id="系列导航">系列导航</h2>
; ]9 l6 U4 P6 R' ~6 |5 [<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>5 j' ^: W% P0 k' d- y
<h2 id="需求">需求</h2>3 f _% w- L8 h0 ^8 x2 I# C
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p># h& i6 P8 `6 k3 M
<h2 id="思路">思路</h2>: H" ~# Y4 T9 J6 x( U2 \3 v) g
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
/ `$ h8 l4 s9 X7 r& y<h2 id="实现">实现</h2>
3 [" [1 ^# b& ~2 o- D: ^7 |$ O<p>为了保持简单,我们先定义以下两个类型:</p>4 A5 ~4 F( g6 ]9 R0 v. A" d( G
<pre><code class="language-c#">// 定义新增Post的参数
5 }9 S* x+ B0 Dpublic record AddPostInput(string Title, string Author);" {5 Z5 k: T4 k; F- ~2 a
4 k5 r7 U3 Z2 r) i }: J; G! j9 t
// 定义新增Post的返回对象
7 w S1 B" d1 K, h+ ipublic record AddPostPayload(Post Post);
- \" @9 z+ r# m4 S! c</code></pre>! `0 o* ?, V5 {% L& y+ G3 H" u
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>2 y0 G) o9 }- _4 A
<ul>
4 c& I4 c! y6 u0 k. @6 @8 w1 q<li><code>Mutation.cs</code></li> q7 i% T8 ^5 |0 n1 B: a
</ul>/ d7 x' Z& F1 N4 j5 I
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
" `) n# d2 Q' Z& Y7 f* Y) Z% K/ ]
" d9 }; \ L% o* tpublic class Mutation
' k5 @' m0 B2 @7 y{. J! l7 B! Z8 N, b3 s Y
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)& }: p6 V3 G% r2 q6 Q- g8 |7 N4 a8 e6 n
{
9 Y3 j3 {; E; `& G5 T4 @2 G9 r3 h return new AddPostPayload(await repository.AddAsync(new Post
/ F2 z- d$ ^# b {, z8 T3 G2 R7 I
Title = input.Title,
, P% ~! r4 z1 M7 B$ Z Author = input.Author8 t2 S( h7 f2 X9 x% C' G: o
}));' n1 H6 l$ L+ M& }# P c
}
# u8 z! J, x9 |( [0 f3 x& r}+ h, }5 m1 m% {+ g2 `( B+ F
0 ^: H* K+ y7 _( ~9 j/ A</code></pre>
5 i4 \4 F2 n+ q$ j<p>最后在注入服务的地方进行配置:</p>
* b, }7 E# d; R- n<ul>- Y* e6 v+ N; _/ T$ ^8 o- C$ k
<li><code>ProgramExtensions.cs</code></li>
3 l! k% Y) j" \</ul>
. B% K# W- H% U* S ^( L! o<pre><code class="language-c#">builder.Services/ b/ V2 e* T8 F' a" R5 n
.AddGraphQLServer()6 C8 l, H T+ ]- c8 q, k J' U
.SetPagingOptions(new PagingOptions
6 j, U. z/ L" i0 z/ y0 O { v" n/ S$ n$ ]: i9 @0 s
MaxPageSize = 50,
3 }" F% s$ y8 F, b; i" H IncludeTotalCount = true2 Z3 e: N( s4 [+ ]
})
# _$ N& k6 r$ u+ H/ T* N; A .AddFiltering()$ h, e( v2 m/ i* i) e
.AddProjections()
' H9 T% r. W7 y' Q .AddSorting()
6 e& P, I L _9 k/ _0 }, P& H .AddQueryType<Query>(). E) d) g5 i% X9 ]/ e- k8 y% d ~
.AddMutationType<Mutation>()& m) t0 q& M8 a- K5 [; F. M
.AddMutationConventions(new MutationConventionOptions$ C3 f& i- Z$ l0 m7 \
{; \8 r5 q5 S( ]: w0 L. W
ApplyToAllMutations = true,/ [* k# B9 h% l
InputArgumentName = "input",; N; H: ]/ p O0 [! h* `
InputTypeNamePattern = "{MutationName}Input",
6 d1 }% }, e6 M7 |! F! s7 Q PayloadTypeNamePattern = "{MutationName}Payload",2 m5 U9 w' M* s
PayloadErrorTypeNamePattern = "{MutationName}Error"," [. u: g: p) T" z- t
PayloadErrorsFieldName = "errors"
4 P- H }7 g1 j: a })) u* W2 A5 N8 A; ] m" B* ?7 v
.AddType<PostType>();
0 x# E, \6 i) e; }: B+ h9 e& @</code></pre>/ K9 T3 T: @! |% ^0 Y
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>5 X+ U0 H# y; H3 K( L
<h2 id="验证">验证</h2>
5 U- ^3 t1 D7 d<p>启动<code>Api</code>项目,调用接口:</p>
, r+ M3 U+ J2 G<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
: o$ w. |; F1 n# I9 S, ^<p>终端的日志输出如下:</p>
" R( Q4 k/ u0 N& n% W7 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']
0 @3 U: [, K. ]1 D1 [INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")0 `* @8 t1 L) @& s3 k0 D. I
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
7 X6 ~& }9 Q% w& P/ m2 X[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'+ G* | K: @/ }' T" t6 Z4 H
</code></pre>
& J! }- { t% B7 w0 ^6 \$ _1 }<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
( Y* e3 b$ u9 n# l3 y<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>$ J) j# G1 H4 O9 Y
<h2 id="总结">总结</h2>
/ P) e+ |( N4 m<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>& v- ?9 A# I: ~7 o9 g. a" z3 x
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
7 C" e3 T' Z! k5 F$ h
/ v$ ~5 {; y2 }1 h |
|