|
- ?" t v" L0 d! G+ l; d4 y<h2 id="系列导航">系列导航</h2>% f! E5 g0 ?, _% x9 p
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>; Y4 y4 G' G6 E4 v! E! n
<h2 id="需求">需求</h2>6 w, D1 w" ? I$ V0 W
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>. R5 ] a! _0 J3 Q
<h2 id="思路">思路</h2>' `7 ]0 q2 P3 O1 t9 G
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>5 ]/ A, z, _/ f# g2 T$ J
<h2 id="实现">实现</h2>
5 k! ^, K. R& z<p>为了保持简单,我们先定义以下两个类型:</p>
o- o! R8 q+ G8 }9 z% R; ~<pre><code class="language-c#">// 定义新增Post的参数
0 w& D/ D* D8 U2 @2 Ypublic record AddPostInput(string Title, string Author);( d R/ ]* M# R0 l. M$ X3 Z+ x
3 U6 Y4 u! D9 q5 l5 f! C6 |
// 定义新增Post的返回对象
: x/ G* K' i( Ypublic record AddPostPayload(Post Post);
8 b2 r. p; e2 T: G0 o/ N0 \; b* J</code></pre>1 t* m4 H1 N; m( M6 T
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>7 E( M! F; ^; k% B
<ul>+ p3 V1 Z0 B( P5 \$ P5 v
<li><code>Mutation.cs</code></li>+ c/ q7 f+ f" m
</ul>( w' N& t7 ?' v8 q
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;) H2 D% r5 W p! Q. D: q
/ d( p4 r/ ^7 w! d2 p, n D: t/ x
public class Mutation
; a) y1 v7 @6 T/ I" j; g{
; |' {2 `6 D9 m) l public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)* ?2 L6 ^( \6 r
{
% k1 a0 ^8 A7 Z return new AddPostPayload(await repository.AddAsync(new Post
( b$ J5 X% E6 J {. A1 G0 [2 D/ I' T
Title = input.Title,
6 _) Y1 b. V7 N7 d Author = input.Author$ [7 |$ w( G1 Z( a
}));
% V" E4 L& D& r! [/ i }% t# d3 O5 V8 j9 j( T- ?6 v" W
}3 R$ @$ y8 M Q4 A: y1 y
9 x( O+ A2 E2 b- T( o
</code></pre>
9 M) B2 ?. @$ M: m# C<p>最后在注入服务的地方进行配置:</p>
5 ^. [# c7 x5 N( a- r1 t6 S, d<ul>
6 ~& m6 ]3 J! X6 a<li><code>ProgramExtensions.cs</code></li>
6 F9 z3 H7 i" d/ [6 _0 I</ul>
! b' N! R- K) m* T7 s<pre><code class="language-c#">builder.Services
$ X$ u$ s6 W& S3 B; i .AddGraphQLServer()
6 [6 E2 t) A( |; @) F7 e% k; c5 w( v1 b9 ~ .SetPagingOptions(new PagingOptions3 `* b9 S( z3 E2 [) V
{
4 M* L$ b( i1 l* h! a MaxPageSize = 50,
/ e, K1 R7 I- E3 T IncludeTotalCount = true
7 ?" ^% e1 q% l! ?2 v })
5 c* v8 C/ z! f2 _+ Y .AddFiltering()
/ [& p5 C( q& h* r .AddProjections()
. w+ C, I" k u* Q- \) s .AddSorting()
" N* {8 m v. i6 L! d .AddQueryType<Query>()
0 e) I; @. b$ e* _3 \7 t .AddMutationType<Mutation>()" Z) |* T* }( M! T/ z
.AddMutationConventions(new MutationConventionOptions
* E$ y* _/ N! x: G+ y {
5 ~+ F9 D& L) ^3 c ApplyToAllMutations = true,7 R# W% Z$ w+ Z7 `4 b
InputArgumentName = "input",) K# P$ Z& y1 M( f
InputTypeNamePattern = "{MutationName}Input",/ D9 j# U: |) y8 |% \
PayloadTypeNamePattern = "{MutationName}Payload",
3 V% F9 H! o1 G' ~ PayloadErrorTypeNamePattern = "{MutationName}Error",
9 ^. w$ z7 c3 u# j% ~* ^$ d' b PayloadErrorsFieldName = "errors"* x4 B! `6 q% A6 q7 d6 G
})
! G$ b0 A' ~: J+ q4 \/ s5 ` .AddType<PostType>();
0 n/ {$ e5 X- a: ]8 z+ ]</code></pre>
+ ~4 z2 G' S/ L% c0 G<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>4 ?" q$ Q. K7 G0 d3 B* p
<h2 id="验证">验证</h2>, w* I f) W9 I1 q5 E; k2 C
<p>启动<code>Api</code>项目,调用接口:</p>8 J. I9 \+ f4 C9 V
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>1 A# n" u, p0 Z
<p>终端的日志输出如下:</p>
, W0 @. l. b; R; z& n- J% y<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 Z' f" Q4 W/ s; \9 F% R- rINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")' N. t' c& W& A+ U/ A, o! z! b
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);% R8 m/ p; _% J" A) b$ S
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'- \ M4 U, z5 Z. m* |" ?8 \
</code></pre>
% |8 r) T$ b# q<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
& B4 c' J7 v @# m6 k# H<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
" P) D' j! Q; ^4 Y/ y% V+ G<h2 id="总结">总结</h2>
9 k9 {2 f" p! }' z2 Q+ }: i( r4 S<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 u: x: J: f5 m9 t9 j; s- B. n<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
) t# D( e3 X% J& h9 I
$ O1 l& k( ~+ ?+ p0 I; G' s |
|