|
|
' i9 M4 I/ c/ E* E: f
<h2 id="系列导航">系列导航</h2>! }/ r+ s# u9 P' ?+ s
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>: [# j4 U: n. k" y9 {# \7 b
<h2 id="需求">需求</h2>
# ^. b3 w% ^+ l! s2 J<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>' G# u( c8 P+ I6 v& C) p. r/ y
<h2 id="思路">思路</h2>
7 T& U0 E: U- y5 v d* V<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>, h8 ?! U- l! U c' N9 D
<h2 id="实现">实现</h2>
& e8 M( H3 D5 t- l. _ b) h<p>为了保持简单,我们先定义以下两个类型:</p>$ z6 @% |7 v! [; [+ y
<pre><code class="language-c#">// 定义新增Post的参数
$ a+ Q M% a7 ~2 bpublic record AddPostInput(string Title, string Author);
9 m; V, c2 X% B ~' n$ ?. z# @. s$ U3 b* X4 m/ p
// 定义新增Post的返回对象
0 ]- Y* o; ]3 ^0 \, G4 x. M hpublic record AddPostPayload(Post Post);$ a* D+ g5 d# @4 X0 G( ` L
</code></pre>
" a# n, b1 F1 W0 H<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>, i( k- f5 J( D" N6 D A: `' a. a
<ul>- A, _" Q6 |5 X& d
<li><code>Mutation.cs</code></li>
3 W9 _$ W/ F- @9 p; U</ul>
0 ^* p2 S! H) I" y# @4 t/ A<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;, S; ^" k$ g' g/ B
, ?: T q2 C/ v# k- D
public class Mutation9 t: Y# V5 N6 z' b. E# M! R) x: X
{7 B3 E" s0 ^; g1 K- R
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)( ]9 U0 ^$ J; I+ I" V- {- L5 I
{+ ~) |' [0 q) H
return new AddPostPayload(await repository.AddAsync(new Post
F' j. ^' b" [) C1 G8 Y0 V: n {+ x4 G0 C* t" N, R" p
Title = input.Title,$ @/ n# ~; V+ E* j; f% i
Author = input.Author
3 C- X( Y- g: l V" \ }));
4 A3 L) c) `6 H2 X& h }
' h7 P. V3 j9 l6 Q* T) `8 R1 I}0 u+ |/ T, W& ~' F4 a
3 f2 I @+ R1 t% c" ]+ v0 o</code></pre>9 ~3 d$ D& ~' O8 b- Q4 |
<p>最后在注入服务的地方进行配置:</p>
# d# c% E! N9 _1 `- }8 Z<ul>
/ j; d' D4 ?! G; ~1 k3 \, ^<li><code>ProgramExtensions.cs</code></li>
, N. H" \0 C1 C# C+ D2 v& n/ f</ul>
. Q/ {, b0 F U3 u* V8 F/ a! C<pre><code class="language-c#">builder.Services2 X& @& [0 x9 J9 j. g9 p: p1 x
.AddGraphQLServer()5 v8 K4 J$ j9 J, ]" f
.SetPagingOptions(new PagingOptions9 C$ t, z! M$ j% R
{
7 x- \; s, y1 ^1 O. r( ? MaxPageSize = 50,
5 C- b7 K0 y! S8 | z! b/ g IncludeTotalCount = true
# k* B' K( e- T- Y# i })
+ t" U* u9 A) K4 ] .AddFiltering()
- D- p4 A7 T3 K- T, e _1 e$ Z+ h' S .AddProjections()) m2 f& @/ Q& }( K1 H% m
.AddSorting()+ C# t" `9 N/ S3 e' b) T5 a+ r
.AddQueryType<Query>()
9 k q( n4 G/ A' X .AddMutationType<Mutation>()5 l7 f. I6 u+ ?& t# Q Y
.AddMutationConventions(new MutationConventionOptions$ a4 `7 w) Z- F0 \+ G4 X( J; m
{
( I8 b& w, ~7 ]1 s, ]; }, c) j ApplyToAllMutations = true,
6 D' \9 q, H, ? j) T InputArgumentName = "input",
& i. u; P9 w g4 A: R0 q InputTypeNamePattern = "{MutationName}Input",
" | s$ T: f5 ` PayloadTypeNamePattern = "{MutationName}Payload",
( x6 w5 A5 b$ q* k# j! L7 A PayloadErrorTypeNamePattern = "{MutationName}Error",
1 i2 D4 T6 \# N. D# I4 v PayloadErrorsFieldName = "errors"
& m4 v6 L9 q: b! d5 G* [: o1 D2 e. W })3 Z" ~) J7 c# ~# d% ^( u& A& n
.AddType<PostType>();. ?; H* r: n K) Z
</code></pre>& O8 d/ E: h& @8 g+ q& M7 y
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>0 h# L; o$ B+ N4 i
<h2 id="验证">验证</h2>; x {7 `- U" e* K0 R
<p>启动<code>Api</code>项目,调用接口:</p>
\1 `; m' \9 L" C0 D# D" a& q<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
- l4 N" a1 p( R h5 T9 t, {<p>终端的日志输出如下:</p>0 k7 {8 V/ {# p1 J% Y* n# ?
<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']
" N/ |" Z$ C k( D7 }INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")0 u" A, o& l. \8 n7 Z
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);4 [! K1 K; z+ u% p
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'4 ~0 M2 z: I' O' a# c4 R% ^
</code></pre>
, g& y+ ]5 _4 V( \<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>3 g" h8 \5 F+ j) y
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
4 C: I3 A, ~0 E$ l; l5 n<h2 id="总结">总结</h2>( |; g$ q# K2 F4 }
<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>. Z7 H& {! }1 l$ V4 u4 I2 v" p2 q
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
$ q# P1 Z- h4 A
. E* a/ g4 e9 `% F6 s+ _ |
|