|
, [. |% {% P F2 x+ s; I' |% i* V
<h2 id="系列导航">系列导航</h2>, j7 A" `" U1 j9 W! B
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
# f6 y3 a+ y: ^ c" E<h2 id="需求">需求</h2>7 Z" R: t2 h# t: R; g9 m9 y/ g
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>$ b: g( t6 Z3 G/ Z
<h2 id="思路">思路</h2>
/ j) M! y. E1 U: D<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
# p4 `6 G6 R8 b7 p<h2 id="实现">实现</h2>
/ i: J; b) ?: _. i, w<p>为了保持简单,我们先定义以下两个类型:</p>
; Q z& M. C4 F) x. F<pre><code class="language-c#">// 定义新增Post的参数 M% F K4 O% F& B* J
public record AddPostInput(string Title, string Author);
$ {0 N1 z5 M- m: `" w
# q$ u0 ?8 G7 M7 z2 a. K2 L// 定义新增Post的返回对象! J/ e' Q) p3 ~8 u8 g: O
public record AddPostPayload(Post Post);
% D n! \" M8 o4 W</code></pre>" G' i% c& E) ?! y/ ]' H
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
3 ?$ ?& ~& `* T4 I5 q8 S<ul>
\7 E2 I' q, V7 z/ c4 [, r<li><code>Mutation.cs</code></li>+ A( l( e9 L+ c9 W7 s n, P2 R
</ul>
$ G6 L: @: ~1 d7 ?8 k" q: I<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;1 L8 s! u1 W6 o: |3 I/ G
# J' \# t6 I9 Ipublic class Mutation9 [" h$ K7 \- Y$ C9 M8 u, {
{2 F9 x" t8 D5 w3 o$ f0 j0 k( f
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)8 G+ o# A1 C' Y. B+ l
{) Y$ U( d- ]5 L
return new AddPostPayload(await repository.AddAsync(new Post
& R; H+ t( j! w Y; y, R {; k! `0 S5 _! S* @
Title = input.Title,( W$ M$ R6 o. M# Y* Z5 M, ?# b
Author = input.Author6 f6 Y1 V+ v2 s. `7 F% D3 h
}));% s5 a+ n/ D- I! M3 P3 H
}" a) y, v7 q8 I2 n+ Q
}+ u% w# M: b* n- |
4 n" }4 g7 C% K& B</code></pre>
7 l4 f& T0 F9 x- _6 u2 Q<p>最后在注入服务的地方进行配置:</p>
) R* j- @9 V- R<ul>
' |. X' m- ]) K2 o4 H<li><code>ProgramExtensions.cs</code></li>
4 q5 e% Q9 Y) G</ul>: g! y8 N/ M8 s7 K4 s3 |
<pre><code class="language-c#">builder.Services
' t" q% q# H2 c, m .AddGraphQLServer()
+ ]$ B! I. m8 N3 \$ p3 t .SetPagingOptions(new PagingOptions
2 ~- P7 I6 ^: d/ ?7 C9 r7 O. T {3 c# G# L# S+ J! p1 @" `0 d; E2 _
MaxPageSize = 50,: Z/ i ]0 X) ?
IncludeTotalCount = true
$ p( [& N L$ z1 f3 _8 ]6 H }), u8 x+ E% J9 K; t; h
.AddFiltering()3 N, B' u5 ?. T: s8 D' y2 Y6 o2 V
.AddProjections()
# ^8 ?/ Q9 f T- Q .AddSorting()
, {% u6 o0 @, _3 _* N .AddQueryType<Query>()
; B! y' |9 t7 ]; T, o# \ .AddMutationType<Mutation>()/ I$ k/ `0 b2 ~; K: x8 k, @1 E
.AddMutationConventions(new MutationConventionOptions
8 h9 ^/ a) a8 f/ g; ?7 a {
6 W7 R: `5 v' T4 K- [ ApplyToAllMutations = true,* G' U1 k4 B; r/ d/ [1 X
InputArgumentName = "input",' c9 p4 y9 i; E+ w9 m5 A
InputTypeNamePattern = "{MutationName}Input",
+ _9 i0 ?5 O. }* u. o PayloadTypeNamePattern = "{MutationName}Payload",1 b( @+ {4 s; N) O% N5 M
PayloadErrorTypeNamePattern = "{MutationName}Error",
* x" M" a. Q/ q& s3 Y PayloadErrorsFieldName = "errors"! H" n$ Z9 o s, |1 c
}): t3 p5 c2 k2 w( p. l/ _
.AddType<PostType>();4 H) _9 o/ x' z' ]* y* t, o3 l
</code></pre>
/ ]' Y* Q2 W% \. | H<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
6 }. K7 U3 M+ }& }* i: M5 U1 w<h2 id="验证">验证</h2>7 s% s& k: _0 D$ o# _
<p>启动<code>Api</code>项目,调用接口:</p>7 ?& c3 a( f! [, I
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>7 w8 y6 y! U5 `6 {# i
<p>终端的日志输出如下:</p>
; W* Y7 [9 m% F" }<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']7 `. o4 R% D5 ~% n2 a
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
0 o% ?: x4 v6 z2 t, bVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);5 H& w7 |0 R- [7 f; v) ^$ O
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
9 F' ]/ X8 o& R$ q</code></pre>
~. ~+ K9 ?+ |! h! ?9 d<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>. }# x( m: n7 g5 Q- g( r$ N
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
- Z% M% F6 y B R* e% ~<h2 id="总结">总结</h2>$ o/ o5 X; J1 S8 n ~4 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>4 i. t1 `8 y3 p
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>$ R+ `8 w1 C; P
- t: `3 h+ T, r! P" Q
|
|