|
|
# n1 [/ |- A$ y5 n5 s7 e<h2 id="系列导航">系列导航</h2>& i5 P2 D$ }, L+ x
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
- ^2 Z% b/ ?2 F; j# n7 w' H<h2 id="需求">需求</h2>
% M, Q' I0 F( ~! ^<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
1 t! T; d6 ~0 x' Q- g1 L<h2 id="思路">思路</h2>
; q) G; H2 t$ L( }. j. Q6 K7 X2 z<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>' X. d/ X: j+ @6 \; E
<h2 id="实现">实现</h2>. Y x4 [* }% I0 t% C
<p>为了保持简单,我们先定义以下两个类型:</p>2 j! S1 D6 ?& [. ?' [- ^# K9 u
<pre><code class="language-c#">// 定义新增Post的参数
2 _( \' K: V/ T! @6 P/ Ypublic record AddPostInput(string Title, string Author);
0 h0 `% U( U; J* l) a4 T
* O2 T7 D8 e* \1 i// 定义新增Post的返回对象
) N" m U6 @: t% A# [public record AddPostPayload(Post Post);6 ^' ?, x: K+ Y5 d4 R* E N
</code></pre>6 L7 O0 ?9 [7 D* \3 Y" [
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
( v: S( a3 Q- o: ~& b<ul>& r O" x# |3 [+ B p O
<li><code>Mutation.cs</code></li>" c* t K' K7 N) X6 S1 p( o9 H! U3 Y
</ul>
" I1 n+ [6 [5 D0 S<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;7 w, g L. W8 v. t4 ^
5 X" F) s) X6 l' j! r& _: V8 C0 dpublic class Mutation* L& {- b+ {8 @4 L6 H
{. L' U$ R% y) D/ Y
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository). `+ }' E0 F' X7 b) `
{- |- Q; A* B8 g) [4 i
return new AddPostPayload(await repository.AddAsync(new Post
" i; J+ o, E2 z7 E {
! ]( e! ]8 c8 g" \1 u Title = input.Title,
+ G" W: d& p$ E Author = input.Author
/ u. i1 R" K- ~$ k, Z/ F0 J }));3 S& G$ u" u/ l! K. b
}9 i# Z: K$ c: T. V( ]8 h
}
, B& D$ M9 K$ L- n9 W, C5 \, g$ z4 [. q
</code></pre>! r4 {9 C, y8 A, i5 ?4 J
<p>最后在注入服务的地方进行配置:</p>
7 I) {" n- _. [9 c- q% E" i<ul>2 P. l3 F; h$ M! N
<li><code>ProgramExtensions.cs</code></li>
$ h1 H3 o1 l" m5 T% N- j1 d</ul>1 [3 I# X% s5 ?; }
<pre><code class="language-c#">builder.Services! X7 ? X! A9 a$ G) C% P
.AddGraphQLServer()) _) L. `! d$ O5 q# S* E9 C7 _
.SetPagingOptions(new PagingOptions
/ H( d, |: K* u: ^9 h% N {
& Y& j* f4 ~- Y$ R MaxPageSize = 50,8 J1 U3 P' k5 n5 Z7 U# M! m. K% `
IncludeTotalCount = true
2 \: f" K4 G/ ^, ?; G9 u })
4 T- N" k4 K5 W0 l9 Q .AddFiltering()
0 t. G* J! C: w .AddProjections()
/ D: C9 b) M1 N .AddSorting()
5 `3 J3 F7 E& {: q .AddQueryType<Query>()
( r! D$ H: ^& A- C2 w8 m' U3 n6 a .AddMutationType<Mutation>()
9 ^, j0 _4 W7 t7 g2 S .AddMutationConventions(new MutationConventionOptions+ W9 e V/ B2 R L" f) _1 q, E
{
1 A9 ?4 p0 X$ S d% p" s' { ApplyToAllMutations = true,
% c. t3 C. b2 Q7 p InputArgumentName = "input",
1 _$ s/ q# @4 q$ M. m8 S InputTypeNamePattern = "{MutationName}Input",
* f( u3 c; Z6 r- Y" ?1 k$ K: P9 b- b5 O PayloadTypeNamePattern = "{MutationName}Payload",
) Y; G& `+ c5 ] PayloadErrorTypeNamePattern = "{MutationName}Error",
2 |- {2 m5 t6 h PayloadErrorsFieldName = "errors"
) D5 }2 w* @3 C; H* w8 S8 N })
: h* o8 s6 _$ ? .AddType<PostType>();
r- ?8 X! s* {+ Q2 u4 F6 n</code></pre>
/ W- d# ?: Z, c<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
6 V; `$ X0 V8 P, [5 @<h2 id="验证">验证</h2>4 }6 D* |9 F" T+ s9 t7 Z; f
<p>启动<code>Api</code>项目,调用接口:</p>. X# ~; [8 i2 J6 U3 O% S$ M( @
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>9 [5 T% E0 }! U( R# M" Y S6 j6 Y
<p>终端的日志输出如下:</p>, I! G9 m: f9 B( k1 I$ W' k! O7 {, M
<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']( x9 e' Z% w: V, a
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")5 u- h; F9 a- c% X8 L D
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
+ G% r3 @- v; K. a5 R5 o[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'$ T4 K. `) u, U; @2 J9 [
</code></pre>
0 Y7 A% I: E9 [3 @ w/ {! [! y! P<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>/ r: d! t1 {- G. O7 _/ _0 W
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>; X) t$ |5 [ N2 e9 W
<h2 id="总结">总结</h2>$ M6 v2 Q- y% X( C, 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>
2 r a: f. ]; d. c j# g2 M& O# h<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>1 J" e: B0 n+ R/ `
3 T* F" [+ F5 Y2 |5 S" j0 X |
|