|
|
3 B2 Y+ k' M1 Y3 z! j5 t2 b, r0 J
<h2 id="系列导航">系列导航</h2>. h, B& ?0 T/ i4 V
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
5 O: D9 _" E9 J. W0 u- O& h( B7 I<h2 id="需求">需求</h2>" ~- P# E3 G3 c
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
% l' g2 M$ o0 K4 }<h2 id="思路">思路</h2>
! Z5 P5 ]; ]3 a6 [- U<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>) G5 M' X3 B5 H6 J0 D( y
<h2 id="实现">实现</h2>2 z2 V* N& \- b* T+ p* L* W
<p>为了保持简单,我们先定义以下两个类型:</p>+ U9 h$ h2 V, V7 P4 n0 q* m
<pre><code class="language-c#">// 定义新增Post的参数2 Q' W. F8 N: R( F* S6 J
public record AddPostInput(string Title, string Author);
; F# A3 B$ }4 F
/ ~' z$ W8 w, s- e// 定义新增Post的返回对象
, P# F( j, q6 A8 p4 z, J% q1 ?& Cpublic record AddPostPayload(Post Post);
/ z+ v5 w+ {2 E( e/ h [- y' }- J3 O</code></pre>
+ g- J+ c$ @' K& |! q! R+ W<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>4 F7 w& J# ]- S4 o7 \6 n% f+ B
<ul># e# G4 m4 Z- O O6 O
<li><code>Mutation.cs</code></li>7 A6 [. N8 _2 Y# }( M- {, @" i
</ul>% i) ~/ v# x5 n2 l2 S& \4 }5 U7 V
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;' {8 E6 B# A8 G6 w1 ~8 c& y
% T6 f. r) D }. L0 u
public class Mutation
* V1 C! E L% {% C2 C8 L3 d! E8 f{6 Y& ~$ y' r0 O; ~
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
8 H1 f0 M/ }% D% g. S0 _& { {
8 y5 }' ?9 A/ c+ c) z0 Y return new AddPostPayload(await repository.AddAsync(new Post
# L; P! d8 _* P, w( K {
. B. A/ w+ H, f9 u! l6 { Title = input.Title,
# R7 p8 N( N8 D0 u0 b) G. D# K Author = input.Author8 v0 w* z* ]( m- K
}));: i9 V0 ?# m# B6 K1 a# c. M
}2 t( W0 s& e7 |6 f5 N6 M
}2 j p6 {7 _/ ^
; o/ u4 j+ t& R2 f4 T' B5 O</code></pre>
8 Q4 n( b' S9 [6 W/ ]3 Y<p>最后在注入服务的地方进行配置:</p>1 N! y9 r& a+ ?/ J% S2 r
<ul>
8 K% w. G% H5 ~- F3 P<li><code>ProgramExtensions.cs</code></li>
1 Y* V9 T( ]' W m3 m5 V4 O</ul>
7 I2 ?. r9 y3 n<pre><code class="language-c#">builder.Services
# p3 q- B+ m1 c0 q% C .AddGraphQLServer()% u6 D5 }, Z: K3 m. O/ y
.SetPagingOptions(new PagingOptions
, {5 \3 J U5 ~7 h1 A; I1 L {
: S7 h$ B( i$ x MaxPageSize = 50,
9 D6 d& t: V* I6 v2 _5 s IncludeTotalCount = true! |0 b, {: n3 S4 M) `( D: w0 i
})
, R6 q( o, p, M7 m$ ~5 R .AddFiltering()
% p! Z# p% p& D .AddProjections()$ ]+ G/ x% b; x/ {: j3 }/ |
.AddSorting(); f* r) T4 B; R. z& n
.AddQueryType<Query>()
7 e" W5 Y9 Z; m7 M. l .AddMutationType<Mutation>()) [' a4 m7 s. ~* W y! T
.AddMutationConventions(new MutationConventionOptions, V5 M& E% F# F9 T, T
{% x8 ~: H( ~+ S; S1 P
ApplyToAllMutations = true,$ Q$ O- W4 }3 P% n+ T% [
InputArgumentName = "input",9 R5 v: {! d2 r: i9 l( b2 A
InputTypeNamePattern = "{MutationName}Input",& o8 z" c+ {3 {3 w* L
PayloadTypeNamePattern = "{MutationName}Payload",
$ f! Q( g# ]/ i$ s! \2 l PayloadErrorTypeNamePattern = "{MutationName}Error",; V! @ z0 r9 Q" ?! ~5 c
PayloadErrorsFieldName = "errors"
6 k- U* T H+ X' B( ^1 q4 H" u })
I( \& {5 A6 Y4 C9 |: J/ m5 w .AddType<PostType>();
" J* \4 N' p4 e</code></pre>
7 q. R# }5 z7 a9 ^<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
" m" }8 `1 d, p, P5 ^* X<h2 id="验证">验证</h2> F2 k; z; B0 e" K6 p; y: e
<p>启动<code>Api</code>项目,调用接口:</p>4 ~/ G9 r# {1 J* o2 E+ b. S$ v X' `6 w
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
! \# H* Q% |' W<p>终端的日志输出如下:</p>$ S/ Z4 _0 L% v, ^( h
<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']
; P. X! g! p: }" b; CINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title"); \. M1 d: p& T4 A0 g7 c
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);4 a" F6 M, L" j* ?/ d. L4 E- R
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'9 s: a. ~) r. v" `3 ]6 [/ W
</code></pre>
$ U! v _4 u A& S7 B<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>/ h( P0 ^- _5 k, @ R% m5 [% b
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
0 {) D$ o6 P2 ?6 j" U<h2 id="总结">总结</h2>
" a7 w# v! t k a<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>' K( X' o3 \2 p6 z
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
" y8 Q6 O5 F3 P5 X; e8 w2 B x8 ?& O% B6 h W" C7 J7 A
|
|