|
) m7 }: U+ o1 s' R<h2 id="系列导航">系列导航</h2>
: n' }7 e& a7 \; N% M1 ?<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p># b, {$ z) p! M4 w& D8 f' y; @. W7 V
<h2 id="需求">需求</h2>. S* _1 k4 l" i& _8 |
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>7 u: E/ ]3 a& U4 l7 g3 ^: M! Z
<h2 id="思路">思路</h2>
7 q9 L, e l& y<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>" v2 Q% X& H1 ^+ E$ ~8 x9 o: |
<h2 id="实现">实现</h2>) o- z6 Q9 W1 x- s8 C
<p>为了保持简单,我们先定义以下两个类型:</p>$ ]) q1 _3 e" U" c
<pre><code class="language-c#">// 定义新增Post的参数
& T/ G( V1 `) Z6 d# y$ D# Mpublic record AddPostInput(string Title, string Author);5 D7 o* b# N) X0 ~) R6 f
1 ~# b3 O- @; S// 定义新增Post的返回对象
( _4 Y+ y1 ^. [7 K3 |7 t! r1 fpublic record AddPostPayload(Post Post);8 g. K7 R7 P8 j: c' V# p
</code></pre>3 \" ^# j$ ?# {7 E( E" G7 P
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>5 U4 F* W% N# o2 z9 J {( H
<ul>
6 F, j, o) b D3 ?<li><code>Mutation.cs</code></li>
. R2 X) k) o; ^+ t! _* {, ]</ul>
|; D( S( r0 p* x6 j<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
D$ b% |- U7 ~! M3 N8 S3 \1 r" c. ?' C$ v) ~5 M
public class Mutation
: I. b* j$ B, `, Z Z{) N' W/ O' Y! i0 ]. b9 { L3 @' q+ G
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)9 A# c0 g; j' R; v0 U! ]/ F
{& K; u* B9 W6 k. ]& ~9 }
return new AddPostPayload(await repository.AddAsync(new Post
& Z% }, ?/ ?' I* v* m" J {" }9 |- Q4 q' ?% U5 B7 i3 A# x
Title = input.Title,
9 X5 `2 e) p. g- l. e3 r Author = input.Author
# d; t r& Z! u0 Y, x5 n }));/ ^! Q4 _) z2 u& b. D @
}- K, Q& u2 U6 a' t0 h, C, J
}
/ V4 w# L$ v0 X7 h, j) g+ b( _# z% |. H' e. U
</code></pre>8 T7 L% s/ m& Y1 f( h. G
<p>最后在注入服务的地方进行配置:</p>
/ _, Y: { V3 [/ h& K& o" H/ x<ul>
" j, h5 P- }+ `2 [, L' i( r4 Q) W$ n<li><code>ProgramExtensions.cs</code></li>
2 W$ m3 c& {& f u3 I1 y/ u</ul>7 j0 l1 p6 J3 L0 \: A3 D+ E
<pre><code class="language-c#">builder.Services/ H( X- F4 g8 o7 I# w) j( @9 b
.AddGraphQLServer()
" j$ _& H# J( r: t6 Z .SetPagingOptions(new PagingOptions
) ?) ~2 M B3 q: `5 k; U. }) b {
. U( \: R6 Z% p7 f/ U. O6 h MaxPageSize = 50,$ u: b/ n, M# V, R9 H& I+ e# F# |
IncludeTotalCount = true+ Z2 b, r$ A9 ?% m6 h) z4 X
})
. k% ]+ C2 \8 U X1 i% f+ i5 ~ .AddFiltering()& m) b: l8 \; e: B7 X" [ ?
.AddProjections()
, I/ W" X' q. \$ { .AddSorting()
; h- P* }$ ?& j2 A .AddQueryType<Query>()
/ [+ T$ h4 @) W, X# z .AddMutationType<Mutation>()
! e* E- }, `' M/ m( M& n; T .AddMutationConventions(new MutationConventionOptions
5 v. B: H! Z3 F$ F8 l( H {
7 J+ ~+ ?1 s, D2 C+ b5 a. Y ApplyToAllMutations = true,7 ]! l% G6 e8 A) m4 V9 a% `
InputArgumentName = "input",
( e' y+ e& J9 d" m9 x1 E8 p! [ InputTypeNamePattern = "{MutationName}Input",
_6 c; i2 E' q% M" o4 {2 h1 ^4 R PayloadTypeNamePattern = "{MutationName}Payload",7 e4 T7 f! D y5 z" ?3 a6 c1 y, i
PayloadErrorTypeNamePattern = "{MutationName}Error",
) R# t* J! Y3 n+ b# ^9 b0 ~ PayloadErrorsFieldName = "errors"
! w7 d3 u$ t( m" \% i+ F v })1 G; Y! [- s' H }
.AddType<PostType>();
4 J) {9 Y+ o5 N! q* z</code></pre>8 o. y% D- A u, Z- P g7 J
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
: ^9 X/ F! h/ s% ~) ^' k# v<h2 id="验证">验证</h2>
2 ^3 i6 m8 X3 j9 o9 M9 m4 \<p>启动<code>Api</code>项目,调用接口:</p>
" D6 K. o" {+ V/ C: F8 t<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>3 K, B7 P8 Q5 K# r* g
<p>终端的日志输出如下:</p>) c- b: q+ b( ?3 w
<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']1 \" l6 E+ Z- b$ o: ?: R
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
7 K3 I* _9 c+ x7 k- M+ r' pVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
* h6 ~9 V5 B/ J% z+ d[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'% m8 O& Q! d. Q& g4 s
</code></pre>
1 c: H+ A% U) U<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
( Y' x5 Q4 k' l5 |1 J<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
1 q; a: D: t7 U- n3 [ V<h2 id="总结">总结</h2>
/ [: s8 |# b( f5 _+ Y3 y4 _' Y<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>
, w3 e4 E) p/ X7 M% _( G<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
2 G& I( ]9 P6 S% k. ~, o! W. Q x/ ?
|
|