|
|
- C( `6 z0 Q3 n8 }8 N<h2 id="系列导航">系列导航</h2>
c2 B- u6 X# j! `4 y5 ^<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>( Q8 H. k; y; _+ ?. P9 e& T/ m
<h2 id="需求">需求</h2>
; I0 k0 b7 E5 K<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>; B" Q5 M( `; V) j f4 ]; D; b4 e) s
<h2 id="思路">思路</h2>
; U) }- F0 {6 r7 }- S! o/ \<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
! G; _6 E, k4 r$ @+ ~- ^) n& G6 m<h2 id="实现">实现</h2>( ?% }1 n, H j) e0 n% D$ B* p2 R4 [
<p>为了保持简单,我们先定义以下两个类型:</p>
( N5 }- Q6 O" y# o7 p$ V<pre><code class="language-c#">// 定义新增Post的参数: ?7 U) \& }# d: Q) v
public record AddPostInput(string Title, string Author);* \$ _$ `5 v# I! d! A
8 u7 ~9 F4 F1 b- l" T# [* ?// 定义新增Post的返回对象
! n/ b# T. W' Q# ^* C3 Ypublic record AddPostPayload(Post Post);
! {8 M1 \& F% z! i: @0 k</code></pre>. E$ ]% w& i0 I) W$ n0 q$ s
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
3 N; o& o7 ~& g4 r$ d8 t5 e" u<ul>
5 h$ y) b7 A% _2 I _ c5 i. u<li><code>Mutation.cs</code></li>5 E6 }. T& M9 Q$ B, e4 a+ |
</ul>
' U+ B" k, X* p3 H" I! H: S<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
! k; e' ^' q0 t2 }: b7 `* i( G/ d+ E! z- o, L3 k/ ~5 p
public class Mutation
$ h- N- C- F# @' R4 }! j: [0 v{/ X# V0 Z7 D5 S/ P8 ?5 M4 ^0 W* V' Q
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
k$ ^! W4 F, ]0 V2 ]5 t. j$ [ {* O% ^; v8 X/ D( a- ]
return new AddPostPayload(await repository.AddAsync(new Post
- F- V1 I4 d8 y+ ]0 U8 A {' w; ?, D+ @/ `0 I
Title = input.Title,
0 d a1 w; k* r2 f) h' [: B Author = input.Author. `7 T0 U+ s* y) f, `+ ?
}));! H8 w- b: l5 `) M5 s( W2 `
}
! _2 I& i: e$ \, E}/ |* w% J$ n" {# U* V3 C2 r6 l0 ?
6 n& r; _0 t3 b& W
</code></pre>" `: b( ]# v' f$ U' O; I' C
<p>最后在注入服务的地方进行配置:</p>- t, c9 h. K$ @8 j- m) ~# r
<ul>2 u) V$ t0 e N' {2 h5 T# N
<li><code>ProgramExtensions.cs</code></li>
# S, X! x( _! G6 K4 R" s</ul>* P: Y0 h. t7 E! o! v
<pre><code class="language-c#">builder.Services
" }8 M9 I8 ?' }+ z1 F .AddGraphQLServer()2 m$ z* C0 O) K
.SetPagingOptions(new PagingOptions
3 [0 L' K7 k6 J0 K7 j& n {
% b& s8 Q, e y5 |9 Y MaxPageSize = 50,
" P: c8 \" R5 r6 |% s! S IncludeTotalCount = true
5 |* p. C5 E) k( R7 F, s- s6 b' N })$ Y+ L6 \, j; n8 _
.AddFiltering()
: ^2 `$ K, x. \9 _6 O* B* p" c' i .AddProjections()
+ g2 r1 }$ _" n/ d% |; Y: G: x .AddSorting()
; S/ d3 T4 `9 M1 [. d .AddQueryType<Query>()8 A( z' K1 H5 F. `) ~7 z
.AddMutationType<Mutation>()
* t6 m' d& O8 M' Y5 {" b .AddMutationConventions(new MutationConventionOptions
4 A$ e% k+ {1 E/ h' o {3 ~$ v m6 p' K) X; B* N n$ G6 V
ApplyToAllMutations = true,
7 @; Z$ C" f* W U InputArgumentName = "input",
+ B' J# f& [% b7 F InputTypeNamePattern = "{MutationName}Input",
% k/ Q: K7 m2 U* B8 h5 h1 S PayloadTypeNamePattern = "{MutationName}Payload",- [8 H6 k+ j3 z; ]& b
PayloadErrorTypeNamePattern = "{MutationName}Error",
( G8 M6 O; q- V. q PayloadErrorsFieldName = "errors"
- Y# h$ V7 H$ C e })+ `7 \7 H6 W# q9 g6 B) ~5 U
.AddType<PostType>();% j* B# U! g* }9 p" g+ u
</code></pre>
# v8 z: k' d, r- i6 N* a0 x<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
4 `; _$ y/ x* ^' m$ G) v% k<h2 id="验证">验证</h2>
6 s' p* C# u% O7 d$ w' _<p>启动<code>Api</code>项目,调用接口:</p>6 B4 K) Z+ n4 X
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>( x' `9 m; y- V3 ~! l! ~
<p>终端的日志输出如下:</p>& B3 ]$ s z5 J1 V3 w
<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']/ ]. c; B$ b4 N, J
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title"): q, W( ^- G* d5 X, K: B+ g0 y8 Y
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
% z& i& {8 a- G: d2 ?+ B[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'+ \) V, o: E# L; ^* ^
</code></pre>; \. Y# s2 U$ m0 k1 w# T: ]
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
* J( `- j' u- B- c<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>; ^3 ~& o2 q a; r! [8 b
<h2 id="总结">总结</h2>6 Z) \ ^. O$ H7 _* r, r
<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>
3 A" w$ i2 M t6 i3 X<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>; N7 r$ T/ F/ t$ k
- J" Z% V. \1 c- @. e
|
|