|
|
; D, _+ l- }2 S9 g5 y/ _<h2 id="系列导航">系列导航</h2>
$ Q* U% B/ A8 s& Q! w* g. D<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
# @# h- A6 j l7 S8 r9 s3 I<h2 id="需求">需求</h2>. B7 ?% \0 A9 B7 ?0 D% z
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
* ]' o/ i, K5 b0 @- R1 b! A" D<h2 id="思路">思路</h2>
2 B2 F, \0 g( ~5 R<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>( G4 c. j4 p2 z2 ]$ r# w
<h2 id="实现">实现</h2>; i; Q9 S# Y j% d' v: y
<p>为了保持简单,我们先定义以下两个类型:</p>
; K- N) M* w+ e( P3 q<pre><code class="language-c#">// 定义新增Post的参数& |! W# T) e; C9 O& ^( c \
public record AddPostInput(string Title, string Author);
# W2 }, B [7 a" {7 b, D- H! W5 L/ K+ x
- |* r0 P7 N9 J4 j2 s// 定义新增Post的返回对象
+ ?$ X2 R/ F* _public record AddPostPayload(Post Post);
( ]+ {: w/ S- a1 u. i</code></pre>
- M+ m" s) A2 b* Q; L7 Y<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>: \4 H( {1 ~- w- ]
<ul> ^& w8 ?( E! Y) j; {! I2 g
<li><code>Mutation.cs</code></li>$ `- \; X" K+ u% t4 `0 ?
</ul>
. o% n5 v9 P: h1 R/ B6 ^8 ^# y \$ T<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;; U" D: m' {! K& P& ]* M) S6 J' J2 C' \
0 O3 U# b4 N! M2 A9 K4 f& g2 W
public class Mutation
- i) @: J0 M- y0 n( q- n& p{
! ^7 i6 N) @4 D public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)/ J$ ^! d+ K# w' O
{5 s6 K- h0 N% t8 k8 y) E
return new AddPostPayload(await repository.AddAsync(new Post/ n+ u) j- T- p/ c( h
{
* q# @6 r" }/ X Title = input.Title,
2 B8 t- E2 V" S' ]5 s& R2 k0 ^ Author = input.Author% \0 S0 Q+ c/ v R g
}));$ y& v8 C$ D2 G. L- T
}" N+ \- S: i3 g5 M. g o
}4 N3 H& f$ C v5 g
8 U! Q2 I% D: u: W4 |: H& o</code></pre>
, ~ O( F1 M$ Q7 ~5 q<p>最后在注入服务的地方进行配置:</p>
7 J' X z. a2 u8 J% j* ?; k<ul>
6 ]. S5 h- k* \; U<li><code>ProgramExtensions.cs</code></li>
8 C" p+ `1 O4 \</ul>
0 N: j5 c0 G, C/ I7 u* D3 D& L# V<pre><code class="language-c#">builder.Services1 T, i0 j' q( Z# ^8 X) o E1 }9 g
.AddGraphQLServer()
% A ]9 M r. T! T' R* o/ F .SetPagingOptions(new PagingOptions
% {9 I2 X5 m8 I* f; C. w6 q7 @3 u {
6 r$ @/ T2 D! r' w3 D X3 W MaxPageSize = 50,3 E* x! _7 V" q& ~/ F
IncludeTotalCount = true/ M! O2 ]* t6 b7 x7 ]
})
3 s. V9 s2 l9 u) {# x Z .AddFiltering()
4 Z" ~) r* s* G" j .AddProjections()
2 R: b& e8 e M .AddSorting() A u5 N* L( A& S% W ^
.AddQueryType<Query>()% q) Q$ E' g) I+ t Z7 y
.AddMutationType<Mutation>()( j" n0 o( |+ F) E1 P
.AddMutationConventions(new MutationConventionOptions8 \+ A k! T: w: W
{
! v- n6 z, R1 p4 p/ e9 m% O+ p ApplyToAllMutations = true,
2 V; g; O& e0 a |( }4 f. T2 P InputArgumentName = "input",- u2 P2 T4 d& O1 T9 U
InputTypeNamePattern = "{MutationName}Input",3 O% x5 l+ O( e( K+ g& J
PayloadTypeNamePattern = "{MutationName}Payload",- C. G; j F/ m4 W
PayloadErrorTypeNamePattern = "{MutationName}Error",% C1 m) Z5 g: k0 C. A/ a! C
PayloadErrorsFieldName = "errors". Y3 |6 d3 b$ Z( X& D; U% O5 @5 c
})
& o9 w) R4 l0 I9 `% \/ B; N$ Q .AddType<PostType>();" X% m. R& Y- w
</code></pre>
D5 ?3 v& i; V/ o<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
4 ]: ` J: z4 _/ w<h2 id="验证">验证</h2>; D: Q1 Z, a5 R) h' v5 z! _0 s0 v
<p>启动<code>Api</code>项目,调用接口:</p>
$ w' T( G3 p0 L9 N! x<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p> l3 E% L2 r- h0 y7 d1 B! w
<p>终端的日志输出如下:</p>
9 h2 N' Y; A) V, ~$ [7 _<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']
* O+ g6 g8 D& JINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
# {' Z/ k8 J, z# CVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);# T- n/ A4 G6 j, ]/ w
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline') f& I3 F7 d8 ]3 P9 f
</code></pre>4 S4 a* q, b s- [
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
( Z0 T3 u" n ?3 W<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
: B [2 J! S! X8 o<h2 id="总结">总结</h2>
/ `# P, @% P z<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>
- R0 Y2 X) }& n2 m+ b' {) u, U<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
1 }8 T5 {( o2 ]& m5 b* x) L* N& X0 }
5 n, B. Y v( V/ C, U! T: \ |
|