|
|
& a& ?5 k6 \2 n
<h2 id="系列导航">系列导航</h2>
7 d1 z$ ?$ s2 u J2 S |<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
- ?* k+ U; P% p: p) N( y<h2 id="需求">需求</h2># c9 h& y5 e6 _# Y" ?
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
6 X1 K8 ^1 M2 }! T) G. p- J<h2 id="思路">思路</h2>6 L( B! V0 b$ ]& m1 t" Z; {3 u6 z
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
. K; t2 ^1 [" M/ f0 j<h2 id="实现">实现</h2># \( W t9 _/ q
<p>为了保持简单,我们先定义以下两个类型:</p>5 d2 V, V" {5 Y+ x2 O% j
<pre><code class="language-c#">// 定义新增Post的参数6 f2 P8 C" D; ~/ K( o5 Y9 H4 a
public record AddPostInput(string Title, string Author); l8 J. [* Z& `3 Y% h1 a; N
. R+ g! |0 c) ~* m1 A6 U
// 定义新增Post的返回对象4 y3 l6 I( X6 \* R) c2 ]3 c. N! [
public record AddPostPayload(Post Post);
/ ~- R3 R7 x9 ^- j7 V$ M: h</code></pre>
9 \- C, ]# ?2 a) ]( }; W<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>' D5 e& {5 I3 P4 H! a& f
<ul>
$ Y `0 v1 [. `) v<li><code>Mutation.cs</code></li>5 W* j2 O# `, f
</ul>
0 y- F0 [9 U* C+ h: n, E<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;! _/ l# U( I7 }6 X4 V# N+ y0 Q
% T/ z0 w& S) a; D1 }public class Mutation0 u0 ^0 N% x+ F( S9 w# }- V
{4 A; p: V, ] e H. S
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
/ u1 F9 j, W+ q' d9 j( ? {
. e7 k0 G1 `# r return new AddPostPayload(await repository.AddAsync(new Post
+ M6 a2 K$ ~5 q( Y { z( P. V4 m# t, U2 p3 w- O
Title = input.Title,
0 I* _& m; o& f9 d' D( V* b3 N" b, j Author = input.Author
$ _6 Z4 m e# Z; W8 q D }));, p( c/ t E! U W5 ~
}
9 Q" m' }! m" U. f7 ?) d}
9 l" C0 o$ V7 g |! k2 O( ]( o4 c H
& F& j/ H* U" H9 e' M2 H( L</code></pre>- V, x" ]0 Z8 ?3 D) k
<p>最后在注入服务的地方进行配置:</p>+ k8 g1 s$ _3 F. H
<ul>
+ u- x' z1 |4 I. z( x3 o( l<li><code>ProgramExtensions.cs</code></li>
5 x. |7 |8 V8 y1 F/ U! y</ul>3 [; E6 o- v/ \# B" O# b2 Z
<pre><code class="language-c#">builder.Services# X: p$ g0 c% e8 Y2 w) B+ e3 {; p
.AddGraphQLServer()
! o: ]6 X J T( C3 B: M' I! R- G1 C .SetPagingOptions(new PagingOptions6 }; K. I% k' }7 Z7 w* C5 Z* C
{
, g8 T* x- D8 q2 Q/ a MaxPageSize = 50," I$ Z( h: H( U/ Z
IncludeTotalCount = true
* Y2 ]% B1 T- s- c" t2 W })
! H5 E, f" ^# w2 S0 V .AddFiltering()
* ]5 k# W" O9 q .AddProjections()
7 g5 B9 Y2 Q. v+ N .AddSorting()
3 L9 ] d( C& c3 {. W .AddQueryType<Query>()
' [4 N" u1 v H! K' ^$ y .AddMutationType<Mutation>()
2 w* h- _/ P6 t$ S; E( S; j2 @ .AddMutationConventions(new MutationConventionOptions+ K5 a; a8 j3 ]! d ?( e! r- X0 A
{, k3 C! Q9 |( G9 k, V
ApplyToAllMutations = true,
, k" L. T% C1 a8 D. D InputArgumentName = "input",
7 v4 Q# P' ~! b! |7 }/ Q+ y InputTypeNamePattern = "{MutationName}Input",2 X0 E! q! L8 `2 L
PayloadTypeNamePattern = "{MutationName}Payload",& J! n1 M a" _
PayloadErrorTypeNamePattern = "{MutationName}Error",
4 W9 [7 d% s' g7 Y: s6 N PayloadErrorsFieldName = "errors"
: X9 C8 D3 ^. p })
/ w/ O7 T2 [# D% W% B& E .AddType<PostType>();
4 |& a$ s, b. P</code></pre>
3 n. I3 v {- V& Z, y<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
9 L& f# n8 s* A6 ~. W<h2 id="验证">验证</h2>
, X7 c1 s& Y! f& |<p>启动<code>Api</code>项目,调用接口:</p>! v8 B7 t* B* T& i; D' r
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p># i& F0 ?! u4 i+ ?! {0 x; _0 f/ c3 u
<p>终端的日志输出如下:</p>( C8 z1 R" @. ~* M7 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']
7 G$ q! O& d$ nINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")( \* q" h- A% k5 q, g; W( t
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
: M5 w+ q0 f5 {8 Z" }0 ][10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'3 c/ S$ P- Q8 e1 J+ G) ]
</code></pre>0 |) v3 Z& L: f6 t5 i
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p># N& f$ S" C- u& a
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
% B8 C4 J" F% t: u( K<h2 id="总结">总结</h2>
. E8 }* u1 w/ K O- _<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>: {- T' |9 D6 S; J
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
! N X5 e. {" B1 T% p! w% n( M; t, d6 ]4 I4 Y
|
|