|
|
9 m1 j: C5 { B/ _. n3 d<h2 id="系列导航">系列导航</h2>
) ]$ N3 I( ]- P+ l4 o# P9 m- a<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>3 T/ k3 z/ b8 m g/ J8 Y1 p, t M
<h2 id="需求">需求</h2>1 e2 i1 D# J+ T$ O( `. K. M
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
6 B: L$ w( b# x$ Y<h2 id="思路">思路</h2>9 O. @7 }& _5 W' ^; Q
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>. P" V( M6 y. D# ~1 b
<h2 id="实现">实现</h2>7 K; w" X( i9 J, E# ~( i
<p>为了保持简单,我们先定义以下两个类型:</p>
/ l3 w$ E; q0 X* M<pre><code class="language-c#">// 定义新增Post的参数6 I2 S' c' X2 l! P( {' p1 j
public record AddPostInput(string Title, string Author);2 Q. b, w' ]; a- M3 w/ i
! `* ^& F9 \# Y9 n// 定义新增Post的返回对象
8 l" f7 r2 o, \2 \public record AddPostPayload(Post Post);, }: d7 ~2 D( r/ T# o% R- N( m$ L
</code></pre>; {/ R* L( W1 h3 ^
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>1 M- q9 d# `, e8 L& g: J/ h" l
<ul>
( I3 Y, _& n% N) J<li><code>Mutation.cs</code></li>* j2 m8 b" l d
</ul>
0 A+ [ ^# R, g/ k2 L<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
9 k1 B8 W3 ~! A7 \+ a% M/ E* z! U6 C! l
public class Mutation$ Z% Q, O& @- D% S' w
{ o& l7 \5 q1 y0 c' ?$ q
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
: I$ }' N; E( m. H5 Z3 V {' ^4 u4 y5 E( G
return new AddPostPayload(await repository.AddAsync(new Post& v- U# x3 \$ N7 w, A; S0 d0 z' Y2 `. k
{9 L/ Y _% J" ^9 P6 I; A
Title = input.Title,+ p$ \8 r4 s! x3 R* e& L/ |
Author = input.Author
{) w g7 `* G4 n7 [ }));0 x5 j, _3 K% e# ~1 o$ ~% ^! W5 v
}% @5 U0 c/ Y1 c2 B4 S" _
}: C& B# L2 q0 N/ I3 u: S+ S8 `
+ a! k; S. @* {! D- Q$ r</code></pre>
& } y& i' r" K5 ^! y<p>最后在注入服务的地方进行配置:</p>! B- t& m# V/ {5 Z
<ul>
. U1 ^/ J V2 q& v. ?9 R, u<li><code>ProgramExtensions.cs</code></li>8 E6 C% w0 A# G* n
</ul>" ~) D7 r- G1 }
<pre><code class="language-c#">builder.Services# z/ r$ c: b9 h1 v% w0 x6 J
.AddGraphQLServer()1 |; K2 ^! M2 F4 ^. L5 q/ v
.SetPagingOptions(new PagingOptions$ ]) V! h$ E n$ \
{# P# o5 y5 | v. X. R: o/ l
MaxPageSize = 50,
! B- P& c/ q% Z( e( [9 _/ G& h IncludeTotalCount = true- x3 Q; C1 a# q z/ X$ y
})+ B: F* z5 ^1 h1 {, V3 Y0 ~
.AddFiltering()3 v" @% [2 V' t* Z4 g
.AddProjections()
$ }8 y& s7 Y9 g: {% ~ .AddSorting()
( W6 ?7 i# v! e3 w9 F" _ .AddQueryType<Query>()$ T' C( t: s5 @$ g4 ~6 I% o
.AddMutationType<Mutation>()/ t4 C3 j8 }, V: x
.AddMutationConventions(new MutationConventionOptions
3 h7 u3 A3 Q- V {
+ Z/ Z; P7 f9 P2 Y9 M V, c. Q ApplyToAllMutations = true,- y: n5 u2 `+ U: Q) p: c
InputArgumentName = "input",
1 o0 q/ l$ N* `. w! F' ~ InputTypeNamePattern = "{MutationName}Input",; ?$ b4 J9 w) {" S2 x: E5 o- ^
PayloadTypeNamePattern = "{MutationName}Payload",
1 ~3 ]) N9 [; N$ ]1 J6 Q PayloadErrorTypeNamePattern = "{MutationName}Error",
' G3 k0 g/ I# w3 Y F6 e& R PayloadErrorsFieldName = "errors"
9 |' Z8 f% f6 i. j$ E3 f( j })
& v9 e- C- N F5 V9 i4 B2 d' w" _ .AddType<PostType>();& d+ K7 C; F$ U4 m
</code></pre>+ r% d5 s4 ?3 _
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
2 i& P2 W" B& \7 C* s% P# ]<h2 id="验证">验证</h2>; A% W9 Y/ v8 p4 ]! ?
<p>启动<code>Api</code>项目,调用接口:</p>
: W0 n9 E. d1 G- f% b% h<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
3 n8 J: q" a7 C7 o |<p>终端的日志输出如下:</p>
' V5 r7 y% u/ n& x, f$ R3 _ O: i$ G<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']
4 |! r# l- b$ F% k2 [INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")! [/ e3 Y0 G" M
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
; o$ ]7 N% x) g0 c( T/ b2 `[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'* r6 Y- _2 G9 M' d9 G8 z8 {. e
</code></pre>3 i9 y4 R2 h: T0 z: _5 }$ X2 A
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>! i* ?& U$ E7 }4 }6 M
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>: L8 _* N7 o A6 w/ I- ?& [; O" i
<h2 id="总结">总结</h2>3 M, ~5 y+ E% u+ O9 q
<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>+ X K' L, \/ n. P& H- ]0 x m
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>. n% u' Q9 P8 C5 B: S
: J7 ]: A1 b2 o5 w |
|